macro_rules! wire_enum {
(
$(#[$enum_meta:meta])*
$vis:vis enum $name:ident {
$( $(#[$variant_meta:meta])* $variant:ident = $wire:literal ),+ $(,)?
}
) => {
$(#[$enum_meta])*
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
$vis enum $name {
$( $(#[$variant_meta])* $variant, )+
}
impl $name {
pub const ALL: &'static [$name] = &[ $( $name::$variant, )+ ];
pub const NAMES: &'static [&'static str] = &[ $( $wire, )+ ];
pub const fn as_str(&self) -> &'static str {
match self {
$( $name::$variant => $wire, )+
}
}
pub fn from_wire(wire: &str) -> Option<Self> {
match wire {
$( $wire => Some($name::$variant), )+
_ => None,
}
}
}
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::str::FromStr for $name {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
$name::from_wire(s).ok_or_else(|| {
format!(
"{s:?} is not one of the {} values {}",
stringify!($name),
$name::NAMES.join(" | "),
)
})
}
}
impl ::serde::Serialize for $name {
fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> 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,
) -> Result<Self, D::Error> {
struct Visitor;
impl ::serde::de::Visitor<'_> for Visitor {
type Value = $name;
fn expecting(
&self,
f: &mut ::std::fmt::Formatter<'_>,
) -> ::std::fmt::Result {
write!(f, "one of {}", $name::NAMES.join(" | "))
}
fn visit_str<E: ::serde::de::Error>(self, s: &str) -> Result<$name, E> {
$name::from_wire(s)
.ok_or_else(|| E::unknown_variant(s, $name::NAMES))
}
}
deserializer.deserialize_str(Visitor)
}
}
};
}