use rules_derive::rules_derive;
pub trait EnumFromString: Sized {
fn from_str(x: &str) -> Option<Self>;
}
macro_rules! EnumFromString {
(
$attrs:tt
$vis:vis /* require enum */ enum $name:ident (($ty:ty) ($($generics_bindings:tt)*) ($($generics_inner:tt)*) where ($($generics_where:tt)*)) {
$(
$variant_name:ident (/* require unit variant */ unit $($qualified_variant:tt)*) $(= ($discriminant:expr))? {
}
)*
}
) => {
impl $($generics_bindings)* $crate::EnumFromString for $ty where $($generics_where)*
{
fn from_str(x: &str) -> ::std::option::Option<Self> {
mod names {
$(
#[allow(non_upper_case_globals)]
pub const $variant_name: &str = ::std::stringify!($variant_name);
)*
}
match x {
$(
names::$variant_name => ::std::option::Option::Some($($qualified_variant)*),
)*
_ => ::std::option::Option::None,
}
}
}
}
}
#[derive(Debug, PartialEq, Eq)]
#[rules_derive(EnumFromString)]
pub enum Foo {
Foo,
Bar,
Baz,
Quux,
}
fn main() {
assert_eq!(Some(Foo::Foo), Foo::from_str("Foo"));
assert_eq!(Some(Foo::Bar), Foo::from_str("Bar"));
assert_eq!(Some(Foo::Baz), Foo::from_str("Baz"));
assert_eq!(Some(Foo::Quux), Foo::from_str("Quux"));
assert_eq!(None, Foo::from_str("bamboozle"));
}