#![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 { 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