use proc_macro2::{Ident, TokenStream}; use quote::quote; use crate::network::get_field_variant_type; use super::NetworkField; pub(crate) fn to(fields: &Vec) -> Vec { fields .iter() .map(|field| { if !field.skip { let field_rename = match &field.rename { Some(name) => name.clone(), None => format!("{}", field.ident.as_ref().unwrap()).into(), }; let field_name = field.ident.as_ref().unwrap(); let field_type = get_field_variant_type(&field); let field_inner = if field.network { quote! { self.#field_name.to_network().into() } } else { quote! { self.#field_name.clone().into() } }; if let Some(_) = field.variant { quote! { res.insert(#field_rename.to_string(), libquassel::primitive::Variant::#field_type( std::vec::from_elem(#field_inner, 1))); } } else { quote! { res.insert(#field_rename.to_string(), libquassel::primitive::Variant::VariantList( std::vec::from_elem(#field_inner, 1))); } } } else { quote! {} } }) .collect() } pub(crate) fn to_vec(_type_name: &Ident, fields: &Vec) -> TokenStream { let (lists, for_each_inner, map_inserts): ( Vec, Vec, Vec, ) = fields.iter().fold( (Vec::new(), Vec::new(), Vec::new()), |(mut lists, mut for_each_inner, mut map_inserts), field| { if !field.skip { let field_rename = match &field.rename { Some(name) => name.clone(), None => format!("{}", field.ident.as_ref().unwrap()).into(), }; let field_name = field.ident.as_ref().unwrap(); let field_type = get_field_variant_type(&field); let field_inner = if field.network { if field.map { quote! { item.#field_name.to_network_map() } } else { quote! { item.#field_name.to_network() } } } else { quote! { item.#field_name.clone().into() } }; if let Some(_) = field.variant { lists.push(quote! { let mut #field_name: libquassel::primitive::StringList = Vec::with_capacity(self.len()); }); for_each_inner.push(quote! { #field_name.push(#field_inner); }); map_inserts.push(quote! { map.insert(String::from(#field_rename), libquassel::primitive::Variant::StringList(#field_name)); }); } else { lists.push(quote! { let mut #field_name: libquassel::primitive::VariantList = Vec::with_capacity(self.len()); }); for_each_inner.push(quote! { #field_name.push(libquassel::primitive::Variant::#field_type(#field_inner)); }); map_inserts.push(quote! { map.insert(String::from(#field_rename), libquassel::primitive::Variant::VariantList(#field_name)); }); } } return (lists, for_each_inner, map_inserts); }, ); quote! { #(#lists)* let mut map = libquassel::primitive::VariantMap::new(); self.iter().for_each(|item| { #(#for_each_inner)* }); #(#map_inserts)* return map; } } pub(crate) fn from(fields: &Vec) -> Vec { fields .iter() .map(|field| { let field_name = field.ident.as_ref().unwrap(); if field.default { quote! { #field_name: Default::default(), } } else { let field_rename = match &field.rename { Some(name) => name.clone(), None => format!("{}", field.ident.as_ref().unwrap()).into(), }; let field_type = get_field_variant_type(&field); let field_inner = if field.network { quote! { libquassel::message::NetworkList::from_network_list(&mut std::convert::TryInto::try_into(input.remove(0)).unwrap()) } } else { quote! { std::convert::TryInto::try_into(input.remove(0)).unwrap() } }; if let Some(_) = field.variant { quote! { #field_name: match input.get_mut(#field_rename).unwrap() { libquassel::primitive::Variant::#field_type(input) => #field_inner, _ => panic!("#field_name: wrong variant") }, } } else { quote! { #field_name: match input.get_mut(#field_rename).unwrap() { libquassel::primitive::Variant::VariantList(input) => #field_inner, _ => panic!("#field_name: wrong variant") }, } } } }) .collect() } pub(crate) fn from_vec(type_name: &Ident, fields: &Vec, new: bool) -> TokenStream { let field = &fields[0]; let field_rename = match &field.rename { Some(name) => name.clone(), None => format!("{}", field.ident.as_ref().unwrap()).into(), }; let _field_name = field.ident.as_ref().unwrap(); let _field_type = get_field_variant_type(field); let field_variant = match &field.variant { None => quote! {libquassel::primitive::VariantList}, Some(variant_type) => match variant_type.as_str() { "StringList" => quote! {libquassel::primitive::StringList}, "VariantMap" => quote! {libquassel::primitive::VariantMap}, _ => quote! {libquassel::primitive::VariantMap}, }, }; let inner = if new { quote! { #type_name::from_network_map(input) } } else { quote! { #type_name::from_network_list(input) } }; quote! { let marker: #field_variant = std::convert::TryInto::try_into(input.get(#field_rename).unwrap()).unwrap(); let mut res = Vec::new(); for _ in 0..marker.len() { res.push(#inner); } return res; } }