74 lines
1.7 KiB
Rust
74 lines
1.7 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 E` as well as a function `E::from_repr` which
|
||
|
/// will return `Result<E, ReprError>`.
|
||
|
#[macro_export]
|
||
|
macro_rules! c_enum
|
||
|
{
|
||
|
(
|
||
|
$(#[$outer:meta])*
|
||
|
$V:vis enum $E:ident: $T:ty
|
||
|
{
|
||
|
$($value:expr => $Enum:ident,)+
|
||
|
}
|
||
|
) => {
|
||
|
$(#[$outer])*
|
||
|
#[derive(Copy, Clone)]
|
||
|
$V enum $E
|
||
|
{
|
||
|
$($Enum,)+
|
||
|
}
|
||
|
|
||
|
impl $E
|
||
|
{
|
||
|
/// Returns, if representable, the variant of `Self` from `n`.
|
||
|
$V fn from_repr(n: $T) -> Result<Self, ReprError>
|
||
|
{
|
||
|
match n {
|
||
|
$($value => Ok($E::$Enum),)+
|
||
|
n => Err(ReprError(n.into()))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#[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(3)));
|
||
|
assert_eq!(TestEnum::from_repr(4), Err(ReprError(4)));
|
||
|
assert_eq!(TestEnum::from_repr(5), Err(ReprError(5)));
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
#[should_panic]
|
||
|
fn c_enum_should_error() {TestEnum::from_repr(3).unwrap();}
|
||
|
}
|
||
|
|
||
|
// EOF
|