macro_rules! wire_enum {
(
$(#[$meta:meta])*
$vis:vis enum $name:ident {
$(
$(#[$variant_meta:meta])*
$variant:ident => $wire:literal
),+ $(,)?
}
) => {
$(#[$meta])*
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
$vis enum $name {
$(
$(#[$variant_meta])*
$variant,
)+
Unknown(::std::string::String),
}
impl $name {
pub const WIRE_VALUES: &'static [&'static str] = &[$($wire),+];
#[must_use]
pub fn as_str(&self) -> &str {
match self {
$(Self::$variant => $wire,)+
Self::Unknown(value) => value.as_str(),
}
}
#[must_use]
pub fn is_unknown(&self) -> bool {
::std::matches!(self, Self::Unknown(_))
}
}
impl ::std::convert::From<&str> for $name {
fn from(value: &str) -> Self {
match value {
$($wire => Self::$variant,)+
other => Self::Unknown(::std::borrow::ToOwned::to_owned(other)),
}
}
}
impl ::std::convert::From<::std::string::String> for $name {
fn from(value: ::std::string::String) -> Self {
match value.as_str() {
$($wire => Self::$variant,)+
_ => Self::Unknown(value),
}
}
}
impl ::std::str::FromStr for $name {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
::std::result::Result::Ok(Self::from(value))
}
}
impl ::std::fmt::Display for $name {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.write_str(self.as_str())
}
}
impl ::serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
where
S: ::serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}
impl<'de> ::serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
struct WireVisitor;
impl ::serde::de::Visitor<'_> for WireVisitor {
type Value = $name;
fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.write_str(::std::concat!("a ", ::std::stringify!($name), " string"))
}
fn visit_str<E>(self, value: &str) -> ::std::result::Result<Self::Value, E>
where
E: ::serde::de::Error,
{
::std::result::Result::Ok(<$name as ::std::convert::From<&str>>::from(value))
}
fn visit_string<E>(
self,
value: ::std::string::String,
) -> ::std::result::Result<Self::Value, E>
where
E: ::serde::de::Error,
{
::std::result::Result::Ok(
<$name as ::std::convert::From<::std::string::String>>::from(value),
)
}
}
deserializer.deserialize_str(WireVisitor)
}
}
};
}
pub(crate) use wire_enum;