2019-03-01 01:27:14 -08:00
|
|
|
#![doc(hidden)]
|
2019-02-05 01:28:13 -08:00
|
|
|
|
|
|
|
/// Creates an enumeration and function for converting a representation into
|
|
|
|
/// the enumeration type.
|
2019-03-01 01:27:14 -08:00
|
|
|
///
|
|
|
|
/// The syntax is similar to the `bitflags` macro, but each value has the
|
|
|
|
/// syntax `value => enumeration`. `enum` is used instead of `struct`.
|
|
|
|
///
|
2019-03-04 22:05:01 -08:00
|
|
|
/// This will generate an `enum $t` as well as a function `$t::from_repr` which
|
|
|
|
/// will return `Result<$t, ReprError>`.
|
2019-03-04 18:14:09 -08:00
|
|
|
///
|
|
|
|
/// # 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)));
|
|
|
|
/// ```
|
2019-02-05 01:28:13 -08:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! c_enum
|
|
|
|
{
|
|
|
|
(
|
|
|
|
$(#[$outer:meta])*
|
2019-03-04 22:05:01 -08:00
|
|
|
$vi:vis enum $t:ident: $ti:ty
|
2019-02-05 01:28:13 -08:00
|
|
|
{
|
2019-03-09 14:03:20 -08:00
|
|
|
$($(#[$inner:meta])* $va:expr => $en:ident,)+
|
2019-02-05 01:28:13 -08:00
|
|
|
}
|
|
|
|
) => {
|
|
|
|
$(#[$outer])*
|
2019-03-01 20:04:20 -08:00
|
|
|
#[derive(Copy, Clone)]
|
2019-03-04 22:05:01 -08:00
|
|
|
$vi enum $t
|
2019-02-05 01:28:13 -08:00
|
|
|
{
|
2019-03-04 22:05:01 -08:00
|
|
|
$($en,)+
|
2019-02-05 01:28:13 -08:00
|
|
|
}
|
|
|
|
|
2019-03-04 22:05:01 -08:00
|
|
|
impl $t
|
2019-02-05 01:28:13 -08:00
|
|
|
{
|
2019-03-01 01:27:14 -08:00
|
|
|
/// Returns, if representable, the variant of `Self` from `n`.
|
2019-03-04 22:05:01 -08:00
|
|
|
$vi fn from_repr(n: $ti) -> Result<Self, ReprError>
|
2019-02-05 01:28:13 -08:00
|
|
|
{
|
|
|
|
match n {
|
2019-03-09 14:03:20 -08:00
|
|
|
$($(#[$inner])* $va => Ok($t::$en),)+
|
|
|
|
n => Err(ReprError::new(n))
|
2019-02-05 01:28:13 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test
|
|
|
|
{
|
|
|
|
use crate::durandal::err::ReprError;
|
|
|
|
|
|
|
|
c_enum! {
|
|
|
|
#[derive(Debug, PartialEq)]
|
2019-02-24 20:34:59 -08:00
|
|
|
enum TestEnum: u16
|
2019-02-05 01:28:13 -08:00
|
|
|
{
|
|
|
|
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));
|
2019-03-04 05:59:43 -08:00
|
|
|
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)));
|
2019-02-05 01:28:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_panic]
|
2019-02-20 18:33:57 -08:00
|
|
|
fn c_enum_should_error() {TestEnum::from_repr(3).unwrap();}
|
2019-02-05 01:28:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// EOF
|