Maraiah/source/durandal/cenum.rs

97 lines
2.3 KiB
Rust

#![doc(hidden)]
/// Creates an enumeration and function for converting a representation into
/// the enumeration type.
///
/// The syntax is similar to the `bitflags` macro, but each value has the
/// syntax `value => enumeration`. `enum` is used instead of `struct`.
///
/// This will generate an `enum $t` as well as a function `$t::from_repr` which
/// will return `Result<$t, ReprError>`.
///
/// # Examples
///
/// ```
/// use maraiah::{c_enum, durandal::err::ReprError};
///
/// c_enum! {
/// #[derive(Debug, PartialEq)]
/// enum MyEnum: u16
/// {
/// 0 => Zero,
/// 1 => One,
/// 2 => Two,
/// }
/// }
///
/// assert_eq!(MyEnum::from_repr(0), Ok(MyEnum::Zero));
/// assert_eq!(MyEnum::from_repr(1), Ok(MyEnum::One));
/// assert_eq!(MyEnum::from_repr(2), Ok(MyEnum::Two));
/// assert_eq!(MyEnum::from_repr(3), Err(ReprError::new(3)));
/// assert_eq!(MyEnum::from_repr(4), Err(ReprError::new(4)));
/// assert_eq!(MyEnum::from_repr(5), Err(ReprError::new(5)));
/// ```
#[macro_export]
macro_rules! c_enum
{
(
$(#[$outer:meta])*
$vi:vis enum $t:ident: $ti:ty
{
$($(#[$inner:meta])* $va:expr => $en:ident,)+
}
) => {
$(#[$outer])*
#[derive(Copy, Clone)]
$vi enum $t
{
$($en,)+
}
impl $t
{
/// Returns, if representable, the variant of `Self` from `n`.
$vi fn from_repr(n: $ti) -> Result<Self, ReprError>
{
match n {
$($(#[$inner])* $va => Ok($t::$en),)+
n => Err(ReprError::new(n))
}
}
}
};
}
#[cfg(test)]
mod test
{
use crate::durandal::err::ReprError;
c_enum! {
#[derive(Debug, PartialEq)]
enum TestEnum: u16
{
0 => Zero,
1 => One,
2 => Two,
}
}
#[test]
fn c_enum_should_be_ok()
{
assert_eq!(TestEnum::from_repr(0), Ok(TestEnum::Zero));
assert_eq!(TestEnum::from_repr(1), Ok(TestEnum::One));
assert_eq!(TestEnum::from_repr(2), Ok(TestEnum::Two));
assert_eq!(TestEnum::from_repr(3), Err(ReprError::new(3)));
assert_eq!(TestEnum::from_repr(4), Err(ReprError::new(4)));
assert_eq!(TestEnum::from_repr(5), Err(ReprError::new(5)));
}
#[test]
#[should_panic]
fn c_enum_should_error() {TestEnum::from_repr(3).unwrap();}
}
// EOF