macro_rules! string_enum {
(
$(#[$meta:meta])*
$name:ident {
$(
$(#[$vmeta:meta])*
$variant:ident = $value:literal,
)*
}
) => {
$(#[$meta])*
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum $name {
$(
$(#[$vmeta])*
$variant,
)*
Other(String),
}
impl $name {
pub fn as_str(&self) -> &str {
match self {
$(Self::$variant => $value,)*
Self::Other(other) => other,
}
}
}
impl ::std::convert::AsRef<str> for $name {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl ::std::fmt::Display for $name {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.write_str(self.as_str())
}
}
impl ::std::convert::From<&str> for $name {
fn from(value: &str) -> Self {
match value {
$($value => Self::$variant,)*
other => Self::Other(other.to_owned()),
}
}
}
impl ::std::convert::From<String> for $name {
fn from(value: String) -> Self {
Self::from(value.as_str())
}
}
impl ::std::str::FromStr for $name {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self::from(value))
}
}
impl ::serde::Serialize for $name {
fn serialize<S: ::serde::Serializer>(
&self,
serializer: S,
) -> ::std::result::Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
impl<'de> ::serde::Deserialize<'de> for $name {
fn deserialize<D: ::serde::Deserializer<'de>>(
deserializer: D,
) -> ::std::result::Result<Self, D::Error> {
let value = <::std::borrow::Cow<'de, str>>::deserialize(deserializer)?;
Ok(Self::from(value.as_ref()))
}
}
};
}
pub(crate) use string_enum;