fvm-macros 1.0.0

provide the macros for user to write contract more convenient
Documentation
use quote::{
    quote,
    quote_spanned,
};

use proc_macro2::TokenStream as TokenStream2;
use syn::spanned::Spanned as _;
use syn::Type;

pub(crate) fn generate_storage(_attr: TokenStream2, item: TokenStream2) -> TokenStream2 {
    let contract_struct = syn::parse2::<syn::ItemStruct>(item).expect("generate storage error");
    let span = contract_struct.span();
    let ident = contract_struct.ident;
    let fields = contract_struct.fields.iter();

    let field_ident = contract_struct.fields
        .iter()
        .map(|f| f.ident.clone().unwrap())
        .collect::<Vec<proc_macro2::Ident>>();
    // todo: use format_ident!()
    let field_ident_str = contract_struct.fields
        .iter()
        .map(|f| format!("{}", f.ident.clone().unwrap()))
        .collect::<Vec<String>>();
    let field_type = contract_struct.fields
        .iter()
        .map(|f| f.ty.clone())
        .collect::<Vec<Type>>();

    // make the empty struct not warning
    let prefix_token = if field_ident_str.len() > 0 {
        quote! {prefix}
    } else {
        quote! {_prefix}
    };

    quote_spanned!( span=>
        use fvm_std::spread::SpreadLayout;

        pub struct #ident {
            #( #fields ),*
        }

        impl SpreadLayout for #ident {
            fn read_ledger(_key: &[u8], #prefix_token: &[u8]) -> Self {
                #ident {
                    // 此处将field进行展开
                    #(#field_ident: <#field_type>::read_ledger(#field_ident_str.as_bytes(), prefix),)*
                }
            }

            fn write_ledger(&self, _key: &[u8], #prefix_token: &[u8]) {
                #(SpreadLayout::write_ledger(&self.#field_ident, #field_ident_str.as_bytes(), prefix);)*
            }
        }
    )
}