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
//! Internal macros for rate

extern crate proc_macro;
extern crate proc_macro2;

use quote::quote;
use syn;

#[proc_macro_derive(HeapSpace)]
pub fn heap_space(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let ast: syn::DeriveInput = syn::parse(input).unwrap();
    let type_name = ast.ident;
    let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
    let block = match ast.data {
        syn::Data::Struct(ref data_struct) => data_struct
            .fields
            .iter()
            .map(|field| {
                let field_name = &field.ident;
                quote!(self.#field_name.heap_space())
            })
            .fold(quote!(0), |a, b| quote!(#a + #b)),
        syn::Data::Enum(ref data_enum) => data_enum
            .variants
            .iter()
            .map(|field| quote!(self.#field.ident.heap_space()))
            .fold(quote!(0), |a, b| quote!(#a + #b)),
        syn::Data::Union(ref _data_union) => panic!("not implemented for unions"),
    };
    let implementation = quote!(
        impl #impl_generics
        HeapSpace for #type_name #type_generics #where_clause {
            fn heap_space(&self) -> usize {
                #block
            }
        }
    );
    implementation.into()
}