postchain_client_derive/
lib.rs

1extern crate proc_macro;
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::{parse_macro_input, DeriveInput, Data, Fields};
5
6#[proc_macro_derive(StructMetadata)]
7pub fn derive_struct_metadata(input: TokenStream) -> TokenStream {
8    let input = parse_macro_input!(input as DeriveInput);
9    let name = &input.ident;
10
11    let fields = if let Data::Struct(data_struct) = &input.data {
12        if let Fields::Named(fields_named) = &data_struct.fields {
13            &fields_named.named
14        } else {
15            panic!("StructMetadata can only be derived for structs with named fields");
16        }
17    } else {
18        panic!("StructMetadata can only be derived for structs");
19    };
20
21    let field_collector = fields.iter().map(|field| {
22        let field_name = &field.ident;
23        let field_type = &field.ty;
24        quote! {
25            fields.insert(stringify!(#field_name).to_string(), stringify!(#field_type).to_string());
26        }
27    });
28
29    let expanded = quote! {
30        impl StructMetadata for #name {
31            fn field_names_and_types() -> std::collections::BTreeMap<String, String> {
32                let mut fields = std::collections::BTreeMap::new();
33                #(#field_collector)*
34                fields
35            }
36        }
37    };
38
39    TokenStream::from(expanded)
40}