decanter_derive/
lib.rs

1/*
2    Appellation: decanter-derive <library>
3    Creator: FL03 <jo3mccain@icloud.com>
4*/
5extern 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
26/// This function is used to generate the implementation of the Hashable trait.
27fn 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
46/// This function is used to generate the implementation of the Hashable trait.
47fn 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
60// This function is used to generate the implementation of the Hashable trait.
61fn 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}