1extern crate proc_macro;
10
11#[macro_use]
12extern crate syn;
13
14#[macro_use]
15extern crate quote;
16
17use proc_macro::TokenStream;
18use syn::{Data, DeriveInput, Fields, WhereClause, WherePredicate};
19
20#[proc_macro_derive(Zero)]
21pub fn derive_zero(input: TokenStream) -> TokenStream {
22 let input: DeriveInput = syn::parse(input).unwrap();
23
24 let name = input.ident;
25
26 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
27
28 let mut types = vec![];
29
30 match input.data {
31 Data::Struct(ref data) => match data.fields {
32 Fields::Named(ref fields) => for f in &fields.named {
33 types.push(&f.ty);
34 },
35 Fields::Unnamed(ref fields) => for f in &fields.unnamed {
36 types.push(&f.ty);
37 },
38 Fields::Unit => {}
39 },
40 _ => panic!("Can only derive(Zero) for structs"),
41 }
42
43 let mut where_clause = where_clause.cloned().unwrap_or_else(|| WhereClause {
44 where_token: Default::default(),
45 predicates: Default::default(),
46 });
47 for t in types {
48 let p: WherePredicate = parse_quote! { #t: ::boxext::Zero };
49 where_clause.predicates.push(p);
50 }
51
52 let expanded = quote! {
53 unsafe impl #impl_generics ::boxext::Zero for #name #ty_generics #where_clause {}
54 };
55
56 expanded.into()
57}