icon_derive 0.1.0

macros used by icon-utils
Documentation
use proc_macro::{TokenStream};
use quote::quote;
use syn::{parse_macro_input,DeriveInput};


/// Macro used by icon-utils for deriving the Transaction 
/// 
/// # Example
/// ```
/// #[derive(Transaction)]
/// #[sort]
/// struct ExampleTransaction {
///     method: String,
///     params: ExampleParams
/// }
/// ```
#[proc_macro_derive(Transaction)]
pub fn transaction(input: TokenStream) -> TokenStream {
    let DeriveInput {ident, attrs, mut data,    ..} = parse_macro_input!(input as DeriveInput);
    let fields = match &mut data {
        syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(fields), ..}) => &fields.named,
        _ => panic!("Only structs with named fields are supported"),
        
    };
    let paramType = fields.iter().find(|f| f.ident.as_ref().unwrap() == "params").unwrap().ty.clone();
    let output = quote! {
        impl icon_utils::serializer::Transaction for &#ident {
            type Params = #paramType;
            fn params(&self) -> &Self::Params {
                &self.params
            }
            fn method(&self) -> &String {
                &self.method
            } 
        }
    };
    output.into()
}
/// Macro used by icon-utils for sorting the fields of a struct alphabetically
/// 
/// # Example
/// ```
/// #[derive(Transaction)]
/// #[sort]
/// struct ExampleTransaction {
///     method: String,
///     params: ExampleParams
/// }
/// ```
#[proc_macro_attribute]
pub fn sort(_args: TokenStream, input: TokenStream) -> TokenStream{
    let mut ast = parse_macro_input!(input as syn::DeriveInput);
    let ident = &ast.ident;
    let data = &ast.data;
    let fields = match &data {
        syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(fields), ..}) => &fields.named,
        _ => panic!("Only structs with named fields are supported"),
    };
    let mut newFields: Vec<&syn::Field> = fields.iter().collect();
    newFields.sort_by(|a, b| a.ident.as_ref().unwrap().cmp(&b.ident.as_ref().unwrap()));
    let mut ast2 = ast.clone();
    let mut data2 = &mut ast2.data;
    match &mut data2 {
        syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(fields), ..}) => {
            fields.named.clear();
            for i in newFields {
                fields.named.push(i.clone());
            }
        },
        _ => panic!("Only structs with named fields are supported"),
        
    }
    return quote! {
        #ast2
    }.into()
}