aboutsummaryrefslogtreecommitdiff
path: root/derive/src
diff options
context:
space:
mode:
Diffstat (limited to 'derive/src')
-rw-r--r--derive/src/from/mod.rs90
-rw-r--r--derive/src/from_network_impl.rs127
-rw-r--r--derive/src/lib.rs210
-rw-r--r--derive/src/network/list.rs83
-rw-r--r--derive/src/network/map.rs78
-rw-r--r--derive/src/network/maplist.rs167
-rw-r--r--derive/src/network/mod.rs230
-rw-r--r--derive/src/to_network_impl.rs96
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()
-}