I'm exploring proc_macros
and so far things are going quite well. With the following code, I am able to assign an enum variant to the fields of a struct:
// lib.rs
#[derive(FromMeta, Debug)]
enum VariantType {
VariantOne,
VariantTwo,
}
#[derive(FromField)]
#[darling(attributes(variant_type), forward_attrs(ident))]
struct MyFieldArgs {
ident: Option<Ident>,
var_type: VariantType,
}
#[derive(FromDeriveInput)]
#[darling(supports(struct_named), forward_attrs(ident, data))]
struct MyStructArgs {
pub name: Option<String>,
pub ident: Ident,
pub data: darling::ast::Data<(), MyFieldArgs>,
}
#[proc_macro_derive(VariantFields, attributes(variant_type))]
#[allow(non_snake_case)]
pub fn VariantFields(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as DeriveInput);
let my_struct_args = match MyStructArgs::from_derive_input(&input) {
Ok(args) => args,
Err(e) => return TokenStream::from(e.write_errors()),
};
let field_variants_debug = my_struct_args
.data
.map_struct_fields(|args| format!("{:?}", args.var_type))
.take_struct()
.expect("Expected Struct type")
.into_iter();
quote!(
fn print_variants() {
#( println!("{:?}", #field_variants_debug) ); *
}
)
.into()
}
// main.rs
use proc_macros::VariantFields;
#[derive(VariantFields)]
pub struct Person {
#[variant_type(var_type = "variant_one")]
first_name: String,
#[variant_type(var_type = "variant_one")]
last_name: String,
#[variant_type(var_type = "variant_two")]
age: u32,
}
fn main() {
print_variants();
}
This gives me the output;
"VariantOne"
"VariantOne"
"VariantTwo"
I'm wondering if there is a way for me to simplify the field attributes by replacing those variant_type(var_type = "some_variant"
with just;
#[derive(VariantFields)]
pub struct Person {
#[VariantOne)]
first_name: String,
#[VariantOne)]
last_name: String,
#[VariantTwo]
age: u32,
}
I can modify the line proc macro declaration to #[proc_macro_derive(VariantFields, attributes(VariantOne, VariantTwo))]
, however I can't get further than that. I can't figure out a way for darling
(or another crate) to parse those as the enum on the nested field. Can anyone provide any advice?
Also, this is the first time I've ever touched proc_macros, so if my implementation can be simplified or improved in any way, please let me know.