macro_rules! ordered_enum {
(
$(#[$meta:meta])*
$vis:vis enum $name:ident {
$( $(#[$variant_meta:meta])* $variant:ident ),+ $(,)?
}
) => {
$(#[$meta])*
$vis enum $name {
$( $(#[$variant_meta])* $variant ),+
}
impl $name {
pub const ALL: &[Self] = &[$( Self::$variant ),+];
pub fn position(self) -> usize {
Self::ALL.iter().position(|v| *v == self).expect("ALL lists every variant")
}
#[allow(dead_code)] pub fn next(self) -> Self {
Self::ALL[(self.position() + 1) % Self::ALL.len()]
}
}
};
}
macro_rules! named_enum {
(
$(#[$meta:meta])*
$vis:vis enum $name:ident {
$( $(#[$variant_meta:meta])* $variant:ident => $text:literal ),+ $(,)?
}
) => {
$crate::enums::ordered_enum! {
$(#[$meta])*
$vis enum $name {
$( $(#[$variant_meta])* $variant ),+
}
}
impl $name {
pub fn as_str(self) -> &'static str {
match self {
$( Self::$variant => $text ),+
}
}
pub fn parse(s: &str) -> Option<Self> {
Self::ALL.iter().copied().find(|v| v.as_str() == s.trim())
}
#[allow(dead_code)] pub fn names(separator: &str) -> String {
Self::ALL.iter().map(|v| v.as_str()).collect::<Vec<_>>().join(separator)
}
}
};
}
pub(crate) use {named_enum, ordered_enum};
#[cfg(test)]
#[path = "../tests/enums.rs"]
mod tests;