Reputation: 18591
I would like to use a Rust macro to introduce enum variants alongside "bespoke" ones. As a simple illustration:
macro_rules! make_beta {
() => {Beta}
}
enum Greek {
Alpha,
make_beta! ()
}
My real goal is to have a family:
macro_rules! make_variants {
($($N:literal)+) => {
$(
Array$N([u8; $N]),
)+
}
}
enum Stuff {
Empty,
Something,
make_variants! { 1 2 3 4 5 6 7 8 }
}
which has Array1
through Array8
in addition to "bespoke" variants. Unfortunately neither of these compiles: it complains about the exclamation mark example.
How can I introduce enum variants with a macro?
Upvotes: 2
Views: 2511
Reputation: 1107
Instead of defining the macro inside the enum
, you could define the enum
inside a macro like this:
macro_rules! enum_variants {
($name:ident {$($vals:tt)*} [$($tag:ident : $N:literal)+]) => {
enum $name {
$($vals)*
$($tag([u8; $N])),+,
}
}
}
enum_variants! { Stuff {
Empty,
Something(i32),
}
[A1:1 A2:2 A3:3 A4:4 A5:5 A6:6 A7:7 A8:8]
}
fn main() {
let x = Stuff::A3;
let y = Stuff::Something(3);
}
UDPATE: Using the paste
crate as mentioned by Frxstrem in the comments:
macro_rules! enum_variants {
($name:ident {$($vals:tt)*} [$($N:literal)+]) => {
paste::item!{
enum $name {
$($vals)*
$([<Array $N>]([u8; $N])),+,
}
}
}
}
enum_variants! { Stuff {
Empty,
Something(i32),
}
[1 2 3 4 5 6 7 8]
}
Upvotes: 3