1extern crate proc_macro;
6extern crate quote;
7extern crate syn;
8
9pub(crate) mod internal;
10
11use internal::*;
12
13use proc_macro::TokenStream;
14use quote::quote;
15use syn::{parse_macro_input, DeriveInput, Result};
16
17#[proc_macro_derive(Hashable, attributes(decanter))]
18pub fn hashable(input: TokenStream) -> TokenStream {
19 let ast = parse_macro_input!(input as DeriveInput);
20
21 let gen = impl_hashable(&ast);
22
23 gen.expect("").into()
24}
25
26fn impl_hashable(ast: &DeriveInput) -> Result<proc_macro2::TokenStream> {
28 let ctxt = Ctxt::new();
29 let cont = match ast::Container::from_ast(&ctxt, ast) {
30 Some(cont) => cont,
31 None => return Err(ctxt.check().unwrap_err()),
32 };
33 ctxt.check()?;
34 derive_hash(&cont)
35}
36
37fn derive_hash(cont: &ast::Container) -> Result<proc_macro2::TokenStream> {
38 let attr = cont.attrs();
39 let res = match attr.uses() {
40 attr::HashType::Serde => hash_serde_body(&cont),
41 attr::HashType::String => hash_string_body(&cont),
42 };
43 Ok(res)
44}
45
46fn hash_serde_body(cont: &ast::Container) -> proc_macro2::TokenStream {
48 let attr = cont.attrs();
49 let decanter = attr.crate_path();
50 let ident = cont.ident();
51 quote! {
52 impl #decanter::hash::Hashable for #ident {
53 fn hash(&self) -> #decanter::hash::H256 {
54 #decanter::hash::hash_serialize(&self)
55 }
56 }
57 }
58}
59
60fn hash_string_body(cont: &ast::Container) -> proc_macro2::TokenStream {
62 let attr = cont.attrs();
63 let decanter = attr.crate_path();
64 let ident = cont.ident();
65
66 quote! {
67 impl #decanter::hash::Hashable for #ident {
68 fn hash(&self) -> #decanter::hash::H256 {
69 #decanter::hash::hasher(self.to_string()).into()
70 }
71 }
72 }
73}