Is it possible for a macro to generate structs and enums using the same base fields without repeating them?

Suppose multiple structs and enums need to be generated following the template:

struct D {
 // base
 a: TypeA,
 b: TypeB,
 c: TypeC,

 // extension
 d: TypeD,
}

enum E {
 Remote {
  // ...
 },
 InLine {
  // base
  a: TypeA,
  b: TypeB,
  c: TypeC,

  // extension
  e: TypeE,

 },
}

Is it possible to generate both types of items without repeating the base fields?

Note: Wrapping is not an option because I need serde's deny_unknown_fields which conflicts with serde's flatten.

I'm not the best at writing macros and think what I came up with is pretty ugly, so someone may give you a better one, but yes it's possible. (Under Tools you can Expand Macros by the way.)

1 Like

Thanks.

I was using tt because some fields take attributes. But that is solvable with meta fragments.

And I wanted to generate items separately. But that's not an absolute requirement.

So, all in all, your approach is workable.

Thanks again.

1 Like

Any idea how to fix those errors: playground?

I've been reading around. And I think the kind of macro I would like to write would become possible when ignore from the declarative macro metavariable expressions RFC gets implemented.

For, now, an uglier macro would have to do.

@MoSal being able to add attrs is perfectly possible; the issue lies in performing "products" of different repetitions. Such a thing is not directly doable, but in your case, with a bit of recursion to dispatch handling all the extended definitions one by one, there is no issue anymore:

gen_from_base! {
    base {
        #[serde(rename = "bF")]
        bf: Option<String>,
    }
    
    #[derive(Deserialize, Debug)]
    pub struct S {
        /* base inserted here */
        ef: String,
    }
    
    #[derive(Deserialize, Debug)]
    pub struct S2 {
        /* base inserted here */
        pub ef: u8,
    }

    #[derive(Deserialize, Debug)]
    enum Baz {
        Inline {
            /* base inserted here (first enum variant) */
            foo: u16,
        },
        SomeVariant,
    }
}
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.