simple_hash_macro/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro2::Span;
3use syn;
4use quote::quote;
5
6#[proc_macro_derive(Hashable)]
7pub fn hashable_derive(input: TokenStream) -> TokenStream {
8    let ast: syn::DeriveInput = syn::parse(input).unwrap();
9
10    let name = &ast.ident;
11    let fields = match &ast.data {
12        syn::Data::Struct(syn::DataStruct {
13            fields: syn::Fields::Named(fields),
14            ..
15        }) => {
16            &fields.named
17        },
18        syn::Data::Struct(syn::DataStruct {
19            fields: syn::Fields::Unnamed(fields),
20            ..
21        }) => {
22            &fields.unnamed
23        },
24        _ => panic!("Expected a struct"),
25    };
26    let fields: Vec<syn::Ident> = fields.iter().enumerate().map(|(i, f)| f.ident.clone().unwrap_or_else(|| syn::Ident::new(&i.to_string(), Span::call_site()))).collect();
27    let generics = &ast.generics;
28    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
29
30    let fields_code: Vec<_> = fields.into_iter().map(|f| {
31        quote!{
32            self.#f.update(h);
33        }
34    }).collect();
35    let ret = quote! {
36       impl #impl_generics simple_hash::Hashable for #name #ty_generics #where_clause {
37           fn update<H: simple_hash::Hasher>(&self, h: &mut H) {
38               #(#fields_code)*
39           }
40       }
41    };
42
43    ret.into()
44}