use proc_macro2::TokenStream;
use quote::quote;
#[derive(deluxe::ExtractAttributes)]
#[deluxe(attributes(tvm_result))]
pub(crate) struct TVMResultHeaderAttributes {
pub(crate) ensure_empty: Option<bool>, }
pub fn tvm_result_derive_impl(input: proc_macro::TokenStream) -> TokenStream {
let mut input = syn::parse::<syn::DeriveInput>(input).unwrap();
let header_attrs: TVMResultHeaderAttributes = match deluxe::extract_attributes(&mut input) {
Ok(desc) => desc,
Err(e) => return e.into_compile_error(),
};
let name = input.ident;
let fields = if let syn::Data::Struct(syn::DataStruct {
fields: syn::Fields::Named(syn::FieldsNamed { ref named, .. }),
..
}) = input.data
{
named
} else {
unimplemented!("Now it is implemented only for ordinary structs with named fields")
};
let names = fields.clone().into_iter().map(|f| {
let name = &f.ident;
quote! {#name}
});
let assigns = fields.into_iter().rev().map(|f| {
let name = &f.ident;
quote! {
let #name = TVMResult::from_stack(stack)?;
}
});
let ensure_empty = if header_attrs.ensure_empty.unwrap_or(false) {
quote! {stack.ensure_empty()?;}
} else {
quote! {}
};
let expanded = quote! {
impl TVMResult for #name {
fn from_stack(stack: &mut TVMStack) -> TonResult<Self> {
#(#assigns)*
#ensure_empty
Ok(Self {
#(#names,) *
})
}
}
};
expanded
}