derive_struct_fields_macro/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput};
4
5#[proc_macro_derive(StructFields)]
6pub fn derive_struct_fields(input: TokenStream) -> TokenStream {
7    let input = parse_macro_input!(input as DeriveInput);
8    let name = &input.ident;
9    let fields = match input.data {
10        syn::Data::Struct(data) => data.fields,
11        _ => panic!("StructFields can only be derived for structs"),
12    };
13
14    let field_infos: Vec<_> = fields
15        .iter()
16        .map(|f| {
17            let field_name = &f.ident;
18            let field_type = &f.ty;
19            quote! {
20                derive_struct_fields::StructFieldInfo {
21                    name: stringify!(#field_name),
22                    field_type: stringify!(#field_type),
23                }
24            }
25        })
26        .collect();
27
28    let field_names: Vec<_> = fields
29        .iter()
30        .map(|f| {
31            let field_name = &f.ident;
32            quote! {
33                stringify!(#field_name).to_string()
34            }
35        })
36        .collect();
37
38    let expanded = quote! {
39        impl derive_struct_fields::StructFields for #name {
40            fn struct_fields() -> Vec<derive_struct_fields::StructFieldInfo> {
41                vec![ #(#field_infos),* ]
42            }
43            fn struct_field_names() -> Vec<String> {
44                vec![ #(#field_names),* ]
45            }
46
47        }
48    };
49
50    TokenStream::from(expanded)
51}