Reputation: 8092
I am trying to define macro for simplification of creation of enum that is possible convert to/from str:
macro_rules! define_enum_with_str_values {
($Name:ident { $($Variant:ident => $StrVar:expr),* $(,)* }) => {
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum $Name {
$($Variant),*,
}
impl Into<&'static str> for $Name {
fn into(self) -> &'static str {
match self {
$($Name::$Variant => $StrVar),*
}
}
}
impl FromStr for $Name {
type Err = BaseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let obj = match s {
$($StrVar => $Name::$Variant),*
};
Ok(obj)
}
}
}
}
define_enum_with_str_values!(Foo { Aa => "a", Bb => "b" });
This code doesn't compiled, because of I did not define '_'
rule,
but if I define '_'
rule:
impl FromStr for $Name {
type Err = BaseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let obj = match s {
$($StrVar => $Name::$Variant),*
_ => {}
};
Ok(obj)
}
}
I got such compile time error:
error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, `}`, or an operator, found `_`
--> foo.rs:74:25
|
73 | $($StrVar => $Name::$Variant),*
| - expected one of 8 possible tokens here
74 | _ => {}
| ^ unexpected token
...
82 | define_enum_with_str_values!(Foo { Aa => "a", Bb => "b" });
| ----------------------------------------------------------- in this macro invocation
Upvotes: 0
Views: 329
Reputation: 59015
Consider what happens when you expand that macro. The match
in question will look like:
let obj = match s {
"a" => Foo::Aa , "b" => Foo::Bb
_ => {}
};
Note the lack of a comma between the "b"
and _
arms. The simplest fix is to ensure there's always a comma after each arm:
let obj = match s {
$($StrVar => $Name::$Variant,)*
_ => return Err(BaseError)
};
Upvotes: 2