postchain_client_derive/
lib.rs1extern 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}