Reputation: 13
Let's say I have an enum, and I want to somehow annotate or associate each variant with a &str
. E.g.:
enum MyEnum {
A, // "foo"
B(String), // "bar"
C(i32) // "baz"
}
I would also like to collect these &str
's into an array like
const arr:[&'static str; 3] = ["foo", "bar", "baz"];
Is there a nice way to do this automatically at compile time? Rather than having to write out the constant array separately? Perhaps with macros?
A const fn
would answer the first part, but I believe it requires #![feature(const_if_match)]
, and I would prefer using stable Rust if possible. I'm also not sure it answered the second part. I also considered attribute macros, but I don't know how (or whether) you can collect these attributes together at compile time.
Upvotes: 1
Views: 516
Reputation: 15012
You can achieve this with a declarative macro:
macro_rules! str_variants {
{ enum $enum_name:ident {
$(
#[str = $variant_str:literal]
$variant_name:ident $variant_fields:tt
),* $(,)*
} } => {
enum $enum_name {
$(
$variant_name $variant_fields,
)*
}
impl $enum_name {
const ARR: &[&'static str] = &[
$(
$variant_str,
)*
];
}
}
}
str_variants! { enum MyEnum {
#[str = "foo"]
A(),
#[str = "bar"]
B(String),
#[str = "baz"]
C(i32)
} }
fn main() {
dbg!(MyEnum::ARR);
// [src/main.rs:34] MyEnum::ARR = [
// "foo",
// "bar",
// "baz",
// ]
}
You just need to use an extra pair of parens with unit variants.
Upvotes: 0