Derive macro configuration

I've just pushed my first derive macro crate to github: GitHub - KillTheMule/derive_typst_intoval: Derive typst::IntoValue for structs. I'd of course be grateful for any comments or criticism :slight_smile:

I do have one problem with it though. My own usecase kinda demands converting field names to UpperCamelCase, so that's what I did. It's probably not fine for everybody else, so I'm pondering what to do about it. One can put a #[rename] attribute on struct fields to rename with maximum flexibility, but that's kinda unergonomic if the default strategy is bad. What could I do here? Can I make the derive macro take an additional argument for the renaming strategy? A function &str -> String would probably give maximum flexibility, but any choice of trait from heck would probably also be fine.

Note that I could make an additional attribute alright, but as far as I can see a user would have to put it on every field anyways, so there's pretty little gain with that. Or am I missing something?

Thanks for any pointers :wink:

It's common to accept a custom #[your_macro_name(stuff)] for custom derive attributes. For example, serde and derivative use this.

It could look like this:

#[derive(IntoValue)]
#[into_value(rename = "mod::othermod::uppercase")]
struct MyStruct {
  field1: &'static str
}

That looks exactly what I want, thanks.

That being said, I could not understand serde's code here. I was able to extract the argument string (in your example, that would be "mod::othermod::uppercase"), but I need to make that into a function call. I have

quote! {
  #rename(#old).into_string() => self.#ident.into_value()
}

which does what I want if I leave out the #rename(#old) and just use #old there. Of course, there would not be any renaming going on, but the above code fails with

error[E0618]: expected function, found `&'static str`
  --> tests/mod.rs:4:10
   |
4  | #[derive(IntoValue, Clone)]
   |          ^^^^^^^^^
   |          |
   |          call expression requires function
   |          in this derive macro expansion
   |
  ::: /home/pips/Devel/Rust/derive_typst_intoval/src/lib.rs:52:1
   |
52 | pub fn derive_into_value(item: TokenStream) -> TokenStream {
   | ---------------------------------------------------------- in this expansion of `#[derive(IntoValue)]
`

For more information about this error, try `rustc --explain E0618`.
error: could not compile `derive_typst_intoval` (test "mod") due to 1 previous error

Can you give me a hint what I need to use here?

Ah damn, just as I wrote this I found the correct search incantation. I'm using

let f = syn::Ident::new(&rename, ident.span());

for the conversion.

Instead of manually parsing attributes into messy, raw token streams, use deluxe. It's like serde for proc-macro attributes.