pub trait EnumStr: std::marker::Sized {
fn to_str(&self) -> &'static str;
fn from_str(txt: &str) -> Option<Self>;
}
#[macro_export]
macro_rules! enumstr {
( $(#[$meta: meta])*
$enum_name: ident {
$( $variant: ident : $strval: literal ),* $(,)?
}) => {
$(#[$meta])*
#[allow(dead_code)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
pub enum $enum_name {
$( #[doc=$strval]
$variant ),*
}
impl EnumStr for $enum_name {
#[allow(dead_code)]
fn to_str(&self) -> &'static str {
match self {
$( Self::$variant => $strval),*,
}
}
fn from_str(txt: &str) -> Option<Self> {
match txt {
$( $strval => Some(Self::$variant)),*,
_ => None,
}
}
}
impl ::std::fmt::Display for $enum_name {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let s = match self {
$( Self::$variant => $strval),*,
};
write!(f, "{}", s)
}
}
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[test]
fn test_enumstr() {
enumstr!(
LightSwitch {
On: "ON",
Off: "OFF",
}
);
assert_eq!(LightSwitch::On.to_str(), "ON");
assert_eq!(LightSwitch::Off.to_str(), "OFF");
assert_eq!(LightSwitch::from_str("ON"), Some(LightSwitch::On));
assert_eq!(LightSwitch::from_str("OFF"), Some(LightSwitch::Off));
assert_eq!(LightSwitch::from_str("NEITHER"), None);
}
}