diff options
Diffstat (limited to 'derive/src')
| -rw-r--r-- | derive/src/from/mod.rs | 90 | ||||
| -rw-r--r-- | derive/src/from_network_impl.rs | 127 | ||||
| -rw-r--r-- | derive/src/lib.rs | 210 | ||||
| -rw-r--r-- | derive/src/network/list.rs | 83 | ||||
| -rw-r--r-- | derive/src/network/map.rs | 78 | ||||
| -rw-r--r-- | derive/src/network/maplist.rs | 167 | ||||
| -rw-r--r-- | derive/src/network/mod.rs | 230 | ||||
| -rw-r--r-- | derive/src/to_network_impl.rs | 96 |
8 files changed, 652 insertions, 429 deletions
diff --git a/derive/src/from/mod.rs b/derive/src/from/mod.rs new file mode 100644 index 0000000..2855d1a --- /dev/null +++ b/derive/src/from/mod.rs @@ -0,0 +1,90 @@ +use quote::quote; +use syn; +use syn::parse_macro_input; + +use darling::{FromDeriveInput, FromVariant}; + +#[derive(Debug, FromDeriveInput)] +#[darling(attributes(from), supports(enum_any))] +struct Enum { + ident: syn::Ident, + attrs: Vec<syn::Attribute>, +} + +#[derive(Debug, FromVariant)] +#[darling(attributes(from))] +struct EnumField { + ident: syn::Ident, + fields: darling::ast::Fields<syn::Type>, + + #[darling(default)] + ignore: bool, +} + +pub fn from(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(input as syn::DeriveInput); + // println!("{:#?}", input); + + let network = Enum::from_derive_input(&input).unwrap(); + // println!("{:#?}", network); + + let enum_name = network.ident; + + let fields: Vec<EnumField> = match &input.data { + syn::Data::Enum(data) => data + .variants + .iter() + .map(|field| EnumField::from_variant(field).expect("Could not parse field")) + .collect(), + _ => panic!("from: not an enum"), + }; + + let derives = fields + .iter() + .filter(|field| field.fields.fields.len() > 0 && !field.ignore) + .map(|field| { + let variant = &field.ident; + let inner_type = &field.fields.fields[0]; + let inner_type_str = format!("{}", quote! { #inner_type }); + + quote! { + impl From<#inner_type> for #enum_name { + fn from(input: #inner_type) -> Self { + Self::#variant(input) + } + } + + impl std::convert::TryFrom<#enum_name> for #inner_type { + type Error = String; + + fn try_from(input: #enum_name) -> Result<Self, Self::Error> { + match input { + #enum_name::#variant(input) => Ok(input), + v => Err(format!("variant::from: {} wrong variant expected: {:?}", #inner_type_str, v)), + } + } + } + + impl std::convert::TryFrom<&#enum_name> for #inner_type { + type Error = String; + + fn try_from(input: &#enum_name) -> Result<Self, Self::Error> { + match input { + #enum_name::#variant(input) => Ok(input.clone()), + v => Err(format!("variant::from: {} wrong variant expected: {:?}", #inner_type_str, v)), + } + } + } + } + }); + + // println!("{:#?}", fields); + + let gen = quote! { + #(#derives)* + }; + + // println!("{}", gen); + + gen.into() +} diff --git a/derive/src/from_network_impl.rs b/derive/src/from_network_impl.rs deleted file mode 100644 index ff05f1c..0000000 --- a/derive/src/from_network_impl.rs +++ /dev/null @@ -1,127 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; - -use crate::{get_field_type, NetworkField}; - -pub(crate) fn map(fields: &Vec<NetworkField>) -> Vec<TokenStream> { - fields - .iter() - .map(|field| { - 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_type(&field); - - if field.from_map.is_some() { - let field_map: syn::ExprClosure = - syn::parse_str(&field.from_map.as_ref().unwrap()).unwrap(); - - quote! { - #field_name: match &input.get(#field_rename).unwrap() { - crate::primitive::Variant::#field_type(input) => input.iter().map(#field_map).collect(), - _ => unimplemented!() - }, - } - } else { - quote! { - #field_name: match &input.get(#field_rename).unwrap() { - crate::primitive::Variant::#field_type(input) => input.clone(), - _ => unimplemented!() - }, - } - } - }) - .collect() -} - -pub(crate) fn map_list(fields: &Vec<NetworkField>) -> Vec<TokenStream> { - fields - .iter() - .map(|field| { - 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_type(&field); - - if field.from_map.is_some() { - let field_map: syn::ExprClosure = - syn::parse_str(&field.from_map.as_ref().unwrap()).unwrap(); - - quote! { - #field_name: match input.get_mut(#field_rename).unwrap() { - crate::primitive::Variant::VariantList(input) => match &input.remove(0) { - crate::primitive::Variant::#field_type(input) => input.iter().map(#field_map).collect(), - _ => unimplemented!() - }, - _ => unimplemented!() - }, - } - } else { - quote! { - #field_name: match input.get_mut(#field_rename).unwrap() { - crate::primitive::Variant::VariantList(input) => match &input.remove(0) { - crate::primitive::Variant::#field_type(input) => input.clone(), - _ => unimplemented!() - }, - _ => unimplemented!() - }, - } - } - }) - .collect() -} - -pub(crate) fn list(fields: &Vec<NetworkField>) -> Vec<TokenStream> { - fields - .iter() - .map(|field| { - 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_type(&field); - - if field.from_map.is_some() { - let field_map: syn::ExprClosure = - syn::parse_str(&field.from_map.as_ref().unwrap()).unwrap(); - - quote! { - #field_name: match_variant!( - input - .iter() - .nth(input - .iter() - .position(|x| *x == crate::primitive::Variant::ByteArray(#field_rename.to_string())) - .unwrap()) - .unwrap(), - crate::primitive::Variant::#field_type - ).iter().map(#field_map).collect(), - } - } else { - quote! { - #field_name: match_variant!( - input - .iter() - .nth(input - .iter() - .position(|x| *x == Variant::ByteArray(#field_rename.to_string())) - .unwrap() + 1) - .unwrap(), - crate::primitive::Variant::#field_type - ), - } - } - }) - .collect() -} diff --git a/derive/src/lib.rs b/derive/src/lib.rs index ddbb49a..831767a 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -1,216 +1,14 @@ -use quote::quote; use syn; -use syn::parse_macro_input; - -use darling::{FromDeriveInput, FromField, FromMeta, FromVariant}; - -mod from_network_impl; -mod to_network_impl; - -#[derive(Debug, FromDeriveInput)] -#[darling(attributes(network), supports(struct_any))] -struct Network { - ident: syn::Ident, - attrs: Vec<syn::Attribute>, - repr: Repr, -} - -#[derive(Debug, Clone, Copy, FromMeta)] -#[darling(default)] -enum Repr { - Aos, - List, - Map, - Maplist, -} - -impl Default for Repr { - fn default() -> Self { - Repr::List - } -} - -#[derive(Debug, FromField)] -#[darling(attributes(network))] -struct NetworkField { - ident: Option<syn::Ident>, - ty: syn::Type, - - #[darling(default)] - rename: Option<String>, - #[darling(default)] - override_type: Option<String>, - #[darling(default)] - to_map: Option<String>, - #[darling(default)] - from_map: Option<String>, -} +mod from; +mod network; #[proc_macro_derive(Network, attributes(network))] pub fn network(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as syn::DeriveInput); - // println!("{:#?}", input); - - let network = Network::from_derive_input(&input).unwrap(); - // println!("{:#?}", network); - - let fields: Vec<NetworkField> = match &input.data { - syn::Data::Struct(data) => match &data.fields { - syn::Fields::Named(fields) => fields - .named - .iter() - .map(|field| NetworkField::from_field(field).expect("Could not parse field")) - .collect(), - _ => unimplemented!(), - }, - _ => unimplemented!(), - }; - - // println!("{:#?}", fields); - - let name = &input.ident; - - let to_network_impl_center = match network.repr { - // Repr::Aos => {} - Repr::Map => to_network_impl::map(&fields), - Repr::Maplist => to_network_impl::map_list(&fields), - Repr::List => to_network_impl::list(&fields), - _ => unimplemented!(), - }; - - let from_network_impl_center = match network.repr { - // Repr::Aos => {} - Repr::Map => from_network_impl::map(&fields), - Repr::Maplist => from_network_impl::map_list(&fields), - Repr::List => from_network_impl::list(&fields), - _ => unimplemented!(), - }; - - let network_impl_item = match network.repr { - Repr::Aos => quote! {crate::primitive::VariantList;}, - Repr::Map => quote! {crate::primitive::VariantMap;}, - Repr::Maplist => quote! {crate::primitive::VariantMap;}, - Repr::List => quote! {crate::primitive::VariantList;}, - }; - - // do things with `args` - let gen = quote! { - impl crate::message::signalproxy::Network for #name { - type Item = #network_impl_item - - fn to_network(&self) -> Self::Item { - let mut res = Self::Item::new(); - - #(#to_network_impl_center)* - - return res; - } - - fn from_network(input: &mut Self::Item) -> Self { - Self { - #(#from_network_impl_center)* - } - } - } - }; - - println!("{}", gen); - - gen.into() -} - -fn get_field_type(field: &NetworkField) -> syn::Type { - match &field.override_type { - Some(override_type) => syn::Type::from(syn::TypePath { - qself: None, - path: syn::Path { - leading_colon: None, - segments: { - let mut res = - syn::punctuated::Punctuated::<syn::PathSegment, syn::token::Colon2>::new(); - - res.push(syn::PathSegment { - ident: syn::Ident::new(override_type, proc_macro2::Span::call_site()), - arguments: syn::PathArguments::None, - }); - - res - }, - }, - }), - None => field.ty.clone(), - } -} - -#[derive(Debug, FromDeriveInput)] -#[darling(attributes(from), supports(enum_any))] -struct Enum { - ident: syn::Ident, - attrs: Vec<syn::Attribute>, -} - -#[derive(Debug, FromVariant)] -#[darling(attributes(from))] -struct EnumField { - ident: syn::Ident, - fields: darling::ast::Fields<syn::Type>, - - #[darling(default)] - ignore: bool, + network::network(input) } #[proc_macro_derive(From, attributes(from))] pub fn from(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as syn::DeriveInput); - // println!("{:#?}", input); - - let network = Enum::from_derive_input(&input).unwrap(); - // println!("{:#?}", network); - - let enum_name = network.ident; - - let fields: Vec<EnumField> = match &input.data { - syn::Data::Enum(data) => data - .variants - .iter() - .map(|field| EnumField::from_variant(field).expect("Could not parse field")) - .collect(), - _ => unimplemented!(), - }; - - let derives = fields - .iter() - .filter(|field| field.fields.fields.len() > 0 && !field.ignore) - .map(|field| { - let variant = &field.ident; - let inner_type = &field.fields.fields[0]; - - quote! { - impl From<#inner_type> for #enum_name { - fn from(input: #inner_type) -> Self { - Self::#variant(input) - } - } - - impl Into<#inner_type> for #enum_name { - fn into(self) -> #inner_type { - match self { - Self::#variant(input) => input, - _ => unimplemented!(), - } - } - } - } - }); - - // println!("{:#?}", fields); - - let gen = quote! { - #(#derives)* - }; - - // println!("{}", gen); - - gen.into() + from::from(input) } diff --git a/derive/src/network/list.rs b/derive/src/network/list.rs new file mode 100644 index 0000000..75aecd0 --- /dev/null +++ b/derive/src/network/list.rs @@ -0,0 +1,83 @@ +use proc_macro2::TokenStream; +use quote::quote; + +use super::{gen_type, get_field_type, get_field_type_colon, get_field_variant_type, NetworkField}; + +pub(crate) fn to(fields: &Vec<NetworkField>) -> Vec<TokenStream> { + fields + .iter() + .map(|field| { + 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_type(&field); + + let field_inner = if field.network { + quote! { self.#field_name.to_network() } + } else { + quote! { self.#field_name.clone() } + }; + + match &field.variant { + Some(variant_type) => { + let variant_type = gen_type(variant_type.as_str()); + quote! { + res.push(crate::primitive::Variant::ByteArray(#field_rename.to_string())); + res.push(crate::primitive::Variant::#variant_type(#field_inner)); + } + } + None => quote! { + res.push(crate::primitive::Variant::ByteArray(#field_rename.to_string())); + res.push(crate::primitive::Variant::#field_type(#field_inner)); + }, + } + }) + .collect() +} + +pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> { + fields + .iter() + .map(|field| { + 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_type(&field); + let field_variant_type = get_field_variant_type(&field); + + let field_type_colon = get_field_type_colon(field_type.clone()); + + let extract_inner = quote! { + let mut i = input.iter(); + i.position(|x| *x == crate::primitive::Variant::ByteArray(String::from(#field_rename))) + .unwrap(); + + match i.next().unwrap() { + crate::primitive::Variant::#field_variant_type(input) => input.clone(), + _ => panic!("network::list::from: wrong variant type"), + } + }; + + if field.network { + quote! { + #field_name: #field_type_colon::from_network(&mut { + #extract_inner + }), + } + } else { + quote! { + #field_name: { + #extract_inner + }, + } + } + }) + .collect() +} diff --git a/derive/src/network/map.rs b/derive/src/network/map.rs new file mode 100644 index 0000000..60f96b5 --- /dev/null +++ b/derive/src/network/map.rs @@ -0,0 +1,78 @@ +use proc_macro2::{Ident, TokenStream}; +use quote::quote; + +use super::{get_field_type, get_field_type_colon, get_field_variant_type, NetworkField}; + +pub(crate) fn to(fields: &Vec<NetworkField>) -> Vec<TokenStream> { + fields + .iter() + .map(|field| { + 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_type(&field); + let field_variant_type = get_field_variant_type(&field); + + let field_inner = if field.network { + quote! { + self.#field_name.to_network() + } + } else { + quote! { + self.#field_name.clone() + } + }; + + quote! { + res.insert(#field_rename.to_string(), + crate::primitive::Variant::#field_variant_type(#field_inner)); + } + }) + .collect() +} + +pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> { + fields + .iter() + .map(|field| { + 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_type(&field); + let _field_variant_type = get_field_variant_type(&field); + + let field_type_colon = get_field_type_colon(field_type.clone()); + + if field.network { + quote! { + #field_name: #field_type_colon::from_network( + &mut std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).unwrap()), + } + } else { + quote! { + #field_name: std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).unwrap(), + } + } + }) + .collect() +} + +pub(crate) fn to_vec(_type_name: &Ident, _fields: &Vec<NetworkField>) -> TokenStream { + quote! { + self.iter().map(|item| { + item.to_network().into() + }).collect() + } +} + +pub(crate) fn from_vec(type_name: &Ident, _fields: &Vec<NetworkField>) -> TokenStream { + quote! { + input.iter().map(|item| #type_name::from_network(&mut std::convert::TryInto::try_into(item).unwrap())).collect() + } +} diff --git a/derive/src/network/maplist.rs b/derive/src/network/maplist.rs new file mode 100644 index 0000000..c92b279 --- /dev/null +++ b/derive/src/network/maplist.rs @@ -0,0 +1,167 @@ +use proc_macro2::{Ident, TokenStream}; +use quote::quote; + +use super::{get_field_type, NetworkField}; + +pub(crate) fn to(fields: &Vec<NetworkField>) -> Vec<TokenStream> { + fields + .iter() + .map(|field| { + 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_type(&field); + + match &field.variant { + Some(variant_type) => match variant_type.as_str() { + "StringList" => quote! { + res.insert(#field_rename.to_string(), + crate::primitive::Variant::StringList( + std::vec::from_elem(self.#field_name.clone(), 1))); + }, + _ => panic!("network::map::to: not one of the avaible variants") + } + None => quote! { + res.insert(#field_rename.to_string(), + crate::primitive::Variant::VariantList( + std::vec::from_elem(crate::primitive::Variant::#field_type(self.#field_name.clone()), 1))); + } + } + }) + .collect() +} + +pub(crate) fn to_vec(_type_name: &Ident, fields: &Vec<NetworkField>) -> TokenStream { + let (lists, for_each_inner, map_inserts): ( + Vec<TokenStream>, + Vec<TokenStream>, + Vec<TokenStream>, + ) = fields.iter().fold( + (Vec::new(), Vec::new(), Vec::new()), + |(mut lists, mut for_each_inner, mut map_inserts), field| { + 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_type(&field); + + match &field.variant { + None => { + lists.push(quote! { + let mut #field_name: crate::primitive::VariantList = Vec::with_capacity(self.len()); + }); + + for_each_inner.push(quote! { + #field_name.push(crate::primitive::Variant::#field_type(item.#field_name.clone())); + }); + + map_inserts.push(quote! { + map.insert(String::from(#field_rename), crate::primitive::Variant::VariantList(#field_name)); + }); + } + Some(variant_type) => match variant_type.as_str() { + "StringList" => { + lists.push(quote! { + let mut #field_name: crate::primitive::StringList = Vec::with_capacity(self.len()); + }); + + for_each_inner.push(quote! { + #field_name.push(item.#field_name.clone()); + }); + + map_inserts.push(quote! { + map.insert(String::from(#field_rename), crate::primitive::Variant::StringList(#field_name)); + }); + } + _ => panic!("network::map::to: not one of the avaible variants") + } + } + + return (lists, for_each_inner, map_inserts); + }, + ); + + quote! { + #(#lists)* + + let mut map = crate::primitive::VariantMap::new(); + + self.iter().for_each(|item| { + #(#for_each_inner)* + }); + + #(#map_inserts)* + + return map; + } +} + +pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> { + fields + .iter() + .map(|field| { + 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_type(&field); + + match &field.variant { + None => quote! { + #field_name: match input.get_mut(#field_rename).unwrap() { + crate::primitive::Variant::VariantList(input) => std::convert::TryInto::try_into(input.remove(0)).unwrap(), + _ => panic!("#field_name: wrong variant") + }, + }, + Some(variant_type) => match variant_type.as_str() { + "StringList" => quote! { + #field_name: match input.get_mut(#field_rename).unwrap() { + crate::primitive::Variant::StringList(input) => input.remove(0), + _ => panic!("#field_name: wrong variant") + }, + }, + _ => panic!("network::map::to: not one of the avaible variants"), + } + } + }) + .collect() +} + +pub(crate) fn from_vec(type_name: &Ident, fields: &Vec<NetworkField>) -> 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_variant = match &field.variant { + None => quote! {crate::primitive::VariantList}, + Some(variant_type) => match variant_type.as_str() { + "StringList" => quote! {crate::primitive::StringList}, + "VariantMap" => quote! {crate::primitive::VariantMap}, + _ => panic!("network::map::from_vec: not one of the avaible variants"), + }, + }; + + 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(#type_name::from_network(input)); + } + + return res; + } +} diff --git a/derive/src/network/mod.rs b/derive/src/network/mod.rs new file mode 100644 index 0000000..f39bedd --- /dev/null +++ b/derive/src/network/mod.rs @@ -0,0 +1,230 @@ +use quote::quote; +use syn::{self, parse_macro_input}; + +use darling::{FromDeriveInput, FromField, FromMeta}; + +mod list; +mod map; +mod maplist; + +#[derive(Debug, FromDeriveInput)] +#[darling(attributes(network), supports(struct_any))] +/// Derive to and from network methods for quassel objects +pub struct Network { + ident: syn::Ident, + attrs: Vec<syn::Attribute>, + /// Representation to choose for the network format + /// see Repr enum + repr: Repr, +} + +#[derive(Debug, Clone, Copy, FromMeta)] +#[darling(default)] +pub enum Repr { + List, + Map, + Maplist, +} + +impl Default for Repr { + fn default() -> Self { + Repr::List + } +} + +// #[derive(Debug, Clone, Copy, FromMeta)] +// #[darling(default)] +// pub enum Variant { +// Variantlist, +// Stringlist, +// Variantmap, +// Default, +// } + +// impl Default for Variant { +// fn default() -> Self { +// Self::Default +// } +// } + +#[derive(Debug, FromField)] +#[darling(attributes(network))] +pub struct NetworkField { + ident: Option<syn::Ident>, + ty: syn::Type, + + #[darling(default)] + rename: Option<String>, + #[darling(default)] + override_type: Option<String>, + /// Variant to encapsulate this field + /// VariantList (default) or StringList + #[darling(default)] + variant: Option<String>, + /// field is a nested network repr so + /// use to_network and from_network on it + #[darling(default)] + network: bool, +} + +pub fn network(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(input as syn::DeriveInput); + // println!("{:#?}", input); + + let network = Network::from_derive_input(&input).unwrap(); + // println!("{:#?}", network); + + let fields: Vec<NetworkField> = match &input.data { + syn::Data::Struct(data) => match &data.fields { + syn::Fields::Named(fields) => fields + .named + .iter() + .map(|field| NetworkField::from_field(field).expect("Could not parse field")) + .collect(), + _ => panic!("network: not a named field"), + }, + _ => panic!("network: not a Struct"), + }; + + // println!("{:#?}", fields); + + let name = &input.ident; + + let to_network_impl_center = match network.repr { + // Repr::Aos => {} + Repr::Map => map::to(&fields), + Repr::Maplist => maplist::to(&fields), + Repr::List => list::to(&fields), + }; + + let from_network_impl_center = match network.repr { + // Repr::Aos => {} + Repr::Map => map::from(&fields), + Repr::Maplist => maplist::from(&fields), + Repr::List => list::from(&fields), + }; + + let network_impl_item = match network.repr { + Repr::Map => quote! {crate::primitive::VariantMap;}, + Repr::Maplist => quote! {crate::primitive::VariantMap;}, + Repr::List => quote! {crate::primitive::VariantList;}, + }; + + let mut gen = quote! { + impl crate::message::signalproxy::Network for #name { + type Item = #network_impl_item + + fn to_network(&self) -> Self::Item { + let mut res = Self::Item::new(); + + #(#to_network_impl_center)* + + return res; + } + + fn from_network(input: &mut Self::Item) -> Self { + Self { + #(#from_network_impl_center)* + } + } + } + }; + + if let Repr::Maplist | Repr::Map = network.repr { + let network_impl_item_vec = match network.repr { + Repr::Map => quote! {crate::primitive::VariantList;}, + Repr::Maplist => quote! {crate::primitive::VariantMap;}, + Repr::List => quote! {crate::primitive::VariantList;}, + }; + + let to_network_impl_vec_center = match network.repr { + Repr::Maplist => maplist::to_vec(name, &fields), + Repr::Map => map::to_vec(name, &fields), + _ => unimplemented!(), + }; + + let from_network_impl_vec_center = match network.repr { + Repr::Maplist => maplist::from_vec(name, &fields), + Repr::Map => map::from_vec(name, &fields), + _ => unimplemented!(), + }; + + let vec = quote! { + impl crate::message::signalproxy::Network for Vec<#name> { + type Item = #network_impl_item_vec + + fn to_network(&self) -> Self::Item { + #to_network_impl_vec_center + } + + fn from_network(input: &mut Self::Item) -> Self { + #from_network_impl_vec_center + } + } + }; + + gen.extend(vec); + } + + // println!("{}", gen); + + gen.into() +} + +fn get_field_type(field: &NetworkField) -> syn::Type { + if let Some(override_type) = &field.override_type { + gen_type(override_type) + } else { + field.ty.clone() + } +} + +fn get_field_variant_type(field: &NetworkField) -> syn::Type { + match &field.variant { + Some(ty) => gen_type(&ty), + None => { + if let Some(override_type) = &field.override_type { + gen_type(override_type) + } else { + field.ty.clone() + } + } + } +} + +fn gen_type(typ: &str) -> syn::Type { + syn::Type::from(syn::TypePath { + qself: None, + path: syn::Path { + leading_colon: None, + segments: { + let mut res = + syn::punctuated::Punctuated::<syn::PathSegment, syn::token::Colon2>::new(); + + res.push(syn::PathSegment { + ident: syn::Ident::new(typ, proc_macro2::Span::call_site()), + arguments: syn::PathArguments::None, + }); + + res + }, + }, + }) +} + +fn get_field_type_colon(mut ty: syn::Type) -> syn::Type { + match &mut ty { + syn::Type::Path(path) => { + let first_seg = path.path.segments.first_mut().unwrap(); + match &mut first_seg.arguments { + syn::PathArguments::AngleBracketed(bracket) => { + bracket.colon2_token = Some(syn::parse_str("::").unwrap()); + } + _ => (), + } + } + _ => (), + }; + + return ty; +} diff --git a/derive/src/to_network_impl.rs b/derive/src/to_network_impl.rs deleted file mode 100644 index 4a8501d..0000000 --- a/derive/src/to_network_impl.rs +++ /dev/null @@ -1,96 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; - -use crate::{get_field_type, NetworkField}; - -pub(crate) fn map(fields: &Vec<NetworkField>) -> Vec<TokenStream> { - fields - .iter() - .map(|field| { - 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_type(&field); - - if field.to_map.is_some() { - let field_map: syn::ExprClosure = - syn::parse_str(&field.to_map.as_ref().unwrap()).unwrap(); - - quote! { - res.insert(#field_rename.to_string(), - crate::primitive::Variant::#field_type(self.#field_name.iter().map(#field_map).collect())); - } - } else { - quote! { - res.insert(#field_rename.to_string(), - crate::primitive::Variant::#field_type(self.#field_name.clone())); - } - } - }) - .collect() -} - -pub(crate) fn map_list(fields: &Vec<NetworkField>) -> Vec<TokenStream> { - fields - .iter() - .map(|field| { - 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_type(&field); - - if field.to_map.is_some() { - let field_map: syn::ExprClosure = - syn::parse_str(&field.to_map.as_ref().unwrap()).unwrap(); - - quote! { - res.insert(#field_rename.to_string(), - crate::primitive::Variant::VariantList( - std::vec::from_elem(crate::primitive::Variant::#field_type(self.#field_name.iter().map(#field_map).collect()), 1))); - } - } else { - quote! { - res.insert(#field_rename.to_string(), - crate::primitive::Variant::VariantList( - std::vec::from_elem(crate::primitive::Variant::#field_type(self.#field_name.clone()), 1))); - } - } - }) - .collect() -} - -pub(crate) fn list(fields: &Vec<NetworkField>) -> Vec<TokenStream> { - fields - .iter() - .map(|field| { - 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_type(&field); - - if field.to_map.is_some() { - let field_map: syn::ExprClosure = - syn::parse_str(&field.to_map.as_ref().unwrap()).unwrap(); - - quote! { - res.push(crate::primitive::Variant::ByteArray(#field_rename.to_string())); - res.push(crate::primitive::Variant::#field_type(self.#field_name.iter().map(#field_map).collect())); - } - } else { - quote! { - res.push(crate::primitive::Variant::ByteArray(#field_rename.to_string())); - res.push(crate::primitive::Variant::#field_type(self.#field_name.clone())); - } - } - }) - .collect() -} |
