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
extern crate proc_macro;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use proc_macro::TokenStream;
use syn::{Data, DeriveInput, Fields, WhereClause, WherePredicate};
#[proc_macro_derive(Zero)]
pub fn derive_zero(input: TokenStream) -> TokenStream {
let input: DeriveInput = syn::parse(input).unwrap();
let name = input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let mut types = vec![];
match input.data {
Data::Struct(ref data) => match data.fields {
Fields::Named(ref fields) => for f in &fields.named {
types.push(&f.ty);
},
Fields::Unnamed(ref fields) => for f in &fields.unnamed {
types.push(&f.ty);
},
Fields::Unit => {}
},
_ => panic!("Can only derive(Zero) for structs"),
}
let mut where_clause = where_clause.cloned().unwrap_or_else(|| WhereClause {
where_token: Default::default(),
predicates: Default::default(),
});
for t in types {
let p: WherePredicate = parse_quote! { #t: ::boxext::Zero };
where_clause.predicates.push(p);
}
let expanded = quote! {
unsafe impl #impl_generics ::boxext::Zero for #name #ty_generics #where_clause {}
};
expanded.into()
}