elrond-wasm-derive 0.3.2

Elrond WebAssembly smart contract API procedural macros
Documentation

macro_rules! format_ident {
    ($ident:expr, $fstr:expr) => {
        syn::Ident::new(&format!($fstr, $ident), $ident.span())
    };
}

pub fn generate_call_method_name(method_ident: &proc_macro2::Ident) -> proc_macro2::Ident {
    format_ident!(method_ident, "call_{}")
}

pub fn generate_callable_interface_impl_struct_name(trait_ident: &proc_macro2::Ident) -> proc_macro2::Ident {
    format_ident!(trait_ident, "{}Impl")
}

pub fn extract_struct_name(args: syn::AttributeArgs) -> syn::Path {
    if args.len() != 1 {
        panic!("Exactly one argument expected in contract annotation, specifying the implementation struct name.");
    }

    if let syn::NestedMeta::Meta(syn::Meta::Path(path)) = args.get(0).unwrap() {
        path.clone()
    } else {
        panic!("Malformed contract implementation struct name")
    }
}

pub fn extract_methods(contract_trait: &syn::ItemTrait) -> Vec<syn::TraitItemMethod> {
    contract_trait
        .items
        .iter()
        .filter_map(|itm| match itm {
            syn::TraitItem::Method(m) => {
                let msig = &m.sig;
                let bad_self_ref = format!(
                    "ABI function `{}` must have `&self` as its first argument.",
                    msig.ident.to_string()
                );
                match msig.inputs[0] {
                    syn::FnArg::Receiver(ref selfref) => {
                        if !selfref.mutability.is_none() {
                            panic!(bad_self_ref)
                        }
                    }
                    _ => panic!(bad_self_ref),
                }

                Some(m.clone())
            }
            _ => None,
        }).collect()
}

pub fn array_literal(bytes: &[u8]) -> proc_macro2::TokenStream {
    quote! { [ #(#bytes),* ] }
}

pub fn generic_type_single_arg_segment(type_name: &str, parent_path_segment: &syn::PathSegment) -> syn::PathSegment {
    match &parent_path_segment.arguments {
        syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments{args, ..}) => {
            if args.len() != 1 {
                panic!("{} type must have exactly 1 generic type argument", type_name);
            }
            if let syn::GenericArgument::Type(vec_type) = args.first().unwrap() {
                match vec_type {                
                    syn::Type::Path(type_path) => {
                        type_path.path.segments.last().unwrap().clone()
                    },
                    other_type => panic!("Unsupported {} generic type: {:?}, not a path", type_name, other_type)
                }
            } else {
                panic!("{} type arguments must be types", type_name)
            }
        },
        _ => panic!("{} angle brackets expected", type_name)
    }
}