boxext_derive/
lib.rs

1// Copyright 2018 Mike Hommey
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9extern 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}