owasm_abi_utils/
lib.rs

1#[macro_use]
2extern crate quote;
3
4macro_rules! format_ident {
5    ($ident:expr, $fstr:expr) => {
6        syn::Ident::new(&format!($fstr, $ident), $ident.span())
7    };
8}
9
10pub struct Contract {
11    pub trait_name: proc_macro2::Ident,
12    pub endpoint_name: proc_macro2::Ident,
13    pub client_name: proc_macro2::Ident,
14    pub struct_name: proc_macro2::Ident,
15    pub method_sigs: Vec<proc_macro2::TokenStream>,
16    pub method_impls: Vec<proc_macro2::TokenStream>,
17}
18
19impl Contract {
20    pub fn new(contract_trait: &syn::ItemTrait) -> Self {
21        let (method_sigs, method_impls) = split_contract_trait(&contract_trait);
22        Contract {
23            trait_name: format_ident!(contract_trait.ident, "{}"),
24            endpoint_name: format_ident!(contract_trait.ident, "{}Endpoint"),
25            client_name: format_ident!(contract_trait.ident, "{}Client"),
26            struct_name: format_ident!(contract_trait.ident, "{}Inst"),
27            method_sigs: method_sigs,
28            method_impls: method_impls,
29        }
30    }
31}
32
33fn split_contract_trait(
34    contract_trait: &syn::ItemTrait,
35) -> (Vec<proc_macro2::TokenStream>, Vec<proc_macro2::TokenStream>) {
36    contract_trait
37        .items
38        .iter()
39        .filter_map(|itm| match itm {
40            syn::TraitItem::Method(m) => {
41                let msig = &m.sig;
42                let bad_self_ref = format!(
43                    "ABI function `{}` must have `&mut self` as its first argument.",
44                    msig.ident.to_string()
45                );
46                match msig.decl.inputs[0] {
47                    syn::FnArg::SelfRef(ref selfref) => {
48                        if selfref.mutability.is_none() {
49                            panic!(bad_self_ref)
50                        }
51                    }
52                    _ => panic!(bad_self_ref),
53                }
54
55                let mattrs = &m.attrs;
56                let sig = quote! {
57                  #(#mattrs)*
58                  #msig;
59                };
60
61                let body = match m.default {
62                    Some(ref mbody) => {
63                        quote! { #msig { #mbody } }
64                    }
65                    None => quote! {},
66                };
67
68                Some((sig, body))
69            }
70            _ => None,
71        })
72        .unzip()
73}