Hi there!
I wrote a small attribute macro, whose purpose is:
- to add some attributes to a struct
- to implement a trait for the type
My implementation works, but I have a few questions. First, the code:
#[proc_macro_attribute]
pub fn base_actor(args: TokenStream, input: TokenStream) -> TokenStream {
let mut ast: DeriveInput = syn::parse(input).unwrap();
let _ = parse_macro_input!(args as parse::Nothing);
if let Data::Struct(DataStruct {
fields: Fields::Named(fields),
..
}) = &mut ast.data
{
fields.named.push(
syn::Field::parse_named
.parse2(quote! { pub myfield: String })
.unwrap(),
);
} else {
panic!("Unexpected input (missing curly braces?)");
}
let name = &ast.ident;
let gen = quote! {
#ast
impl MyTrait for #name {
fn print_my_field(&self) {
println!("myfield: {}", self.myfield);
}
}
};
gen.into()
}
My first question is: is this an idiomatic enough approach (eg. proper usage of the APIs)?
My second question is: how could I split the two additions (struct modification and trait implementation) into two, possibly pure, functions? Ideally, something like this:
let ast = add_field(ast);
let ast = implement_trait(ast);
quote! { #ast }.into()
Implementing add_field() is not a problem, but I don't know how to easily implement implement_trait. I can think of generating the TokenStream (via quote! { /* impl trait... */ }.into()) and re-parsing it (via syn::parse()), but that sound like a waste.
Thanks!
