98 lines
2.4 KiB
Rust
98 lines
2.4 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 implement `TryFrom` on it which
|
|
/// will return `Result<$t, ReprError>`.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// use maraiah::{c_enum, err::ReprError};
|
|
/// use std::convert::TryFrom;
|
|
///
|
|
/// c_enum! {
|
|
/// enum MyEnum: u16 {
|
|
/// Zero = 0,
|
|
/// One = 1,
|
|
/// Two = 2
|
|
/// }
|
|
/// }
|
|
///
|
|
/// assert_eq!(MyEnum::try_from(0), Ok(MyEnum::Zero));
|
|
/// assert_eq!(MyEnum::try_from(1), Ok(MyEnum::One));
|
|
/// assert_eq!(MyEnum::try_from(2), Ok(MyEnum::Two));
|
|
/// assert_eq!(MyEnum::try_from(3), Err(ReprError::new(3)));
|
|
/// assert_eq!(MyEnum::try_from(4), Err(ReprError::new(4)));
|
|
/// assert_eq!(MyEnum::try_from(5), Err(ReprError::new(5)));
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! c_enum
|
|
{
|
|
(
|
|
$(#[$outer:meta])*
|
|
$vi:vis enum $t:ident: $ti:ident
|
|
{
|
|
$($(#[$vouter:meta])* $en:ident = $va:expr),+ $(,)?
|
|
}
|
|
) => {
|
|
$(#[$outer])*
|
|
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
|
#[repr($ti)]
|
|
$vi enum $t {
|
|
$($(#[$vouter])* $en = $va,)+
|
|
}
|
|
|
|
#[allow(unused_qualifications)]
|
|
impl std::convert::TryFrom<$ti> for $t
|
|
{
|
|
type Error = $crate::err::ReprError;
|
|
|
|
/// Returns, if representable, the variant of `Self` from `n`.
|
|
fn try_from(n: $ti) -> Result<Self, Self::Error>
|
|
{
|
|
match n {
|
|
$($va => Ok($t::$en),)+
|
|
n => Err(Self::Error::new(n))
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test
|
|
{
|
|
use crate::err::ReprError;
|
|
use std::convert::TryFrom;
|
|
|
|
c_enum! {
|
|
enum TestEnum: u16 {
|
|
Zero = 0,
|
|
One = 1,
|
|
Two = 2,
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn c_enum_should_be_ok()
|
|
{
|
|
assert_eq!(TestEnum::try_from(0), Ok(TestEnum::Zero));
|
|
assert_eq!(TestEnum::try_from(1), Ok(TestEnum::One));
|
|
assert_eq!(TestEnum::try_from(2), Ok(TestEnum::Two));
|
|
assert_eq!(TestEnum::try_from(3), Err(ReprError::new(3)));
|
|
assert_eq!(TestEnum::try_from(4), Err(ReprError::new(4)));
|
|
assert_eq!(TestEnum::try_from(5), Err(ReprError::new(5)));
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic]
|
|
fn c_enum_should_error() {TestEnum::try_from(3).unwrap();}
|
|
}
|
|
|
|
// EOF
|