1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
use quote::quote;
use syn;
use syn::parse_macro_input;
use darling::{FromDeriveInput, FromField, FromMeta};
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>,
}
#[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: 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(),
}
}
|