I have the following:
struct Health {
health: f32,
}
struct Position {
position: Vec2,
}
struct Collections {
healths: Vec<Health>,
positions: Vec<Position>,
}
I would like to generate the Collections
struct automatically; I am thinking using a macro?
I thought perhaps I could mark each struct I want to include with a custom attribute and then have a macro which builds the Collections
struct.
How could I do this?
To be able to do something like custom attributes you need to write a proc_macro
, that can do almost anything you need with your code.
For a simpler solution you may try with a normal macro_rules
. For that you will need to enclose your type definitions into a macro that does the parsing, and emits back the type definition plus the extra code you need, in your case the Container
class.
Something like this:
macro_rules! collectables {
(
$(
#[collection=$fname:ident]
$(#[$attr:meta])?
$vis:vis struct $name:ident $def:tt
)*
) => {
// The struct definitions
$(
$(#[$attr])?
$vis struct $name $def
)*
// The container
#[derive(Default, Debug)]
pub struct Collections {
$(
$fname: Vec<$name>,
)*
}
};
}
Now you can use the macro to build your original code (playground):
collectables!{
#[collection=healths]
#[derive(Debug)]
struct Health {
health: f32,
}
#[collection=positions]
#[derive(Debug)]
struct Position {
position: (f32, f32),
}
}
Note that as written the #[collection=xxx]
attribute is mandatory and must be the first in every struct definition.