#![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`. #[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 { match n { $($value => Ok($E::$Enum),)+ 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