1#![recursion_limit="128"]
2
3extern crate proc_macro;
4extern crate syn;
5
6extern crate serde_derive_internals;
7use serde_derive_internals::attr::get_serde_meta_items;
8
9use syn::Meta::{NameValue,Word};
10use syn::NestedMeta::Meta;
11
12#[macro_use]
13extern crate quote;
14
15use proc_macro::TokenStream;
16use syn::{ DeriveInput, Data, Fields, Generics, GenericParam };
17use quote::Tokens;
18
19#[proc_macro_derive( Reflection )]
20pub fn derive_reflection( input: TokenStream) -> TokenStream {
21 let input: DeriveInput = syn::parse( input ).unwrap();
22 let name = input.ident;
23 let generics = add_trait_bounds( input.generics );
24 let ( impl_generics, ty_generics, where_clause ) = generics.split_for_impl();
25 let members = aggregate( &input.data );
26 let schema = generate_schema( &input.data );
27 let ty = generate_ty( &input.data );
28
29 let expanded = quote! {
30 impl #impl_generics ::reflection::Reflection for #name #ty_generics #where_clause {
31 fn ty() -> ::reflection::Type { #ty }
32 fn name() -> ::reflection::Name { Some( String::from( stringify!( #name )))}
33
34 fn schema( id: ::reflection::Id ) -> ::reflection::Schema {
35 let mut tree = {#schema};
36 match &mut tree.root_mut().data {
37 ::reflection::Member::Field( ref mut field ) => {
38 field.id = id;
39 field.tyname = Self::name();
40 field.expander = Some( <#name #ty_generics as Reflection>::members );
41 },
42 ::reflection::Member::Variant( ref mut variant ) => {
43 variant.id = id;
44 },
45 }
46 tree
47 }
48
49 fn members() -> ::reflection::Schemas { #members }
50 }
51 };
52
53 expanded.into()
54}
55
56fn add_trait_bounds( mut generics: Generics ) -> Generics {
57 for param in &mut generics.params {
58 if let GenericParam::Type( ref mut type_param ) = *param {
59 let bound = syn::parse_str( "::reflection::Reflection" ).unwrap();
60 type_param.bounds.push( bound );
61 }
62 }
63 generics
64}
65
66fn is_skipped( attrs: &Vec<syn::Attribute> ) -> bool {
67 for meta_items in attrs.iter().filter_map( get_serde_meta_items ) {
68 for meta_item in meta_items {
69 match meta_item {
70 Meta( Word( word )) if word == "skip_serializing" => {
72 return true
73 }
74 _ => continue
75 }
76 }
77 }
78 false
79}
80
81fn serde_rename( field: &syn::Field ) -> Option<String> {
82 for meta_items in field.attrs.iter().filter_map( get_serde_meta_items ) {
83 for meta_item in meta_items {
84 match meta_item {
85 Meta( NameValue( ref m )) if m.ident == "rename" => {
87 if let syn::Lit::Str( ref lit ) = *&m.lit {
88 return Some( lit.value() )
89 }
90 }
91 _ => continue
92 }
93 }
94 }
95 None
96}
97
98fn generate_ty( data: &Data ) -> Tokens {
99 match *data {
100 Data::Struct(_) => {
101 quote!( ::reflection::Type::Struct )
102 }
103 Data::Enum(_) => {
104 quote!( ::reflection::Type::Enum )
105 }
106 Data::Union(_) => unimplemented!()
107 }
108}
109
110fn generate_schema( data: &Data ) -> Tokens {
111 match *data {
112 Data::Struct(_) => {
113 quote!( ::reflection::field( "_", ::reflection::Type::Struct, None, None ))
114 }
115 Data::Enum(_) => {
116 quote!( ::reflection::field( "_", ::reflection::Type::Enum, None, None ))
117 }
118 Data::Union(_) => unimplemented!()
119 }
120}
121
122fn aggregate( data: &Data ) -> Tokens {
123 match *data {
124 Data::Struct( ref data ) => {
125 match data.fields {
126 Fields::Named( ref fields ) => {
127 let fnames = fields.named.iter().filter( |f| !is_skipped( &f.attrs )).map( |f|
128 match serde_rename(f) {
129 Some( name ) => name,
130 None => f.ident.unwrap().to_string()
131 }
132 );
133 let ftypes1 = fields.named.iter().map( |f| f.ty.clone() );
134 let ftypes2 = fields.named.iter().map( |f| f.ty.clone() );
135 let ftypes3 = fields.named.iter().map( |f| f.ty.clone() );
136 quote! {
137 #(
138 -( ::reflection::field(
139 #fnames,
140 <#ftypes1 as ::reflection::Reflection>::ty(),
141 <#ftypes2 as ::reflection::Reflection>::name(),
142 Some( <#ftypes3 as ::reflection::Reflection>::members )))
143 )*
144 }
145 }
146 Fields::Unnamed( ref fields ) => {
147 let mut i = 0;
148 let indices = fields.unnamed.iter().filter( |f| !is_skipped( &f.attrs )).map( |f|
149 match serde_rename(f) {
150 Some( name ) => name,
151 None => { i += 1; return (i-1).to_string() }
152 }
153 );
154 let ftypes1 = fields.unnamed.iter().map( |f| f.ty.clone() );
155 let ftypes2 = fields.unnamed.iter().map( |f| f.ty.clone() );
156 let ftypes3 = fields.unnamed.iter().map( |f| f.ty.clone() );
157 quote! {
158 #(
159 -( ::reflection::field(
160 #indices,
161 <#ftypes1 as ::reflection::Reflection>::ty(),
162 <#ftypes2 as ::reflection::Reflection>::name(),
163 Some( <#ftypes3 as ::reflection::Reflection>::members )))
164 )*
165 }
166 }
167 Fields::Unit => {
168 quote!( ::reflection::Schemas::new() )
169 }
170 }
171 }
172 Data::Enum( ref data ) => {
173 let vnames = data.variants.iter().map( |v| v.ident );
174
175 let fnames = data.variants.iter().map( |v| {
176 let mut i = 0;
177 v.fields.iter().filter( |f| !is_skipped( &f.attrs )).map( move |f| {
178 match serde_rename(f) {
179 Some( name ) => name,
180 None => {
181 if let Some( ident ) = f.ident {
182 ident.to_string()
183 } else {
184 i += 1;
185 (i-1).to_string()
186 }
187 }
188 }
189 })
190 });
191
192 let ftypes1 = data.variants.iter().map( |v|
193 v.fields.iter().map( |fields| fields.ty.clone() )
194 );
195 let ftypes2 = data.variants.iter().map( |v|
196 v.fields.iter().map( |fields| fields.ty.clone() )
197 );
198 let ftypes3 = data.variants.iter().map( |v|
199 v.fields.iter().map( |fields| fields.ty.clone() )
200 );
201
202 quote! {
203 #(
204 -( ::reflection::variant( stringify!( #vnames ))
205 /(
206 #(
207 -( ::reflection::field(
208 #fnames,
209 <#ftypes1 as ::reflection::Reflection>::ty(),
210 <#ftypes2 as ::reflection::Reflection>::name(),
211 Some( <#ftypes3 as ::reflection::Reflection>::members )))
212 )*
213 )
214 )
215 )*
216 }
217 }
218 Data::Union(_) => unimplemented!()
219 }
220}