105 lines
2.6 KiB
Rust
105 lines
2.6 KiB
Rust
|
/// Create a C exportable enum. These are useful for working with C FFIs.
|
||
|
///
|
||
|
/// As C has no idea about tuples or structs enums
|
||
|
/// using this macro must only contain Unit variants.
|
||
|
#[macro_export]
|
||
|
macro_rules! c_enum
|
||
|
{
|
||
|
{
|
||
|
$(#[$attribute: meta])* enum $name: ident : $fieldType: ty
|
||
|
{
|
||
|
$(
|
||
|
$(#[$variantAttribute: meta])*
|
||
|
variant $variant: ident = $value: expr
|
||
|
),*
|
||
|
}
|
||
|
} =>
|
||
|
{
|
||
|
$(#[$attribute])*
|
||
|
#[repr(C)]
|
||
|
pub enum $name
|
||
|
{
|
||
|
$($(#[$variantAttribute])* $variant = $value,)*
|
||
|
}
|
||
|
|
||
|
impl $name
|
||
|
{
|
||
|
/// Generate a variant of the enum from a given value.
|
||
|
///
|
||
|
/// This is not very performant. Becareful when using this
|
||
|
/// to not use this in a high performance loop.
|
||
|
pub fn from_value(val: $fieldType) -> Option<$name>
|
||
|
{
|
||
|
// This would be better as a match statement, but
|
||
|
// unfortunately, it needs to be a giant set of if
|
||
|
// statements since we only have the expression type
|
||
|
// to work with, not a pattern type.
|
||
|
/*
|
||
|
match val
|
||
|
{
|
||
|
$($value => {Some($name::$variant)})*
|
||
|
|
||
|
_ => {None}
|
||
|
}
|
||
|
*/
|
||
|
$(if val == $value {return Some($name::$variant);})*
|
||
|
|
||
|
// No variant was found.
|
||
|
None
|
||
|
}
|
||
|
|
||
|
/// 'true', if the given value matches a variant
|
||
|
/// of the enumeration; Otherwise, 'false'.
|
||
|
pub fn is_valid_value(val: $fieldType) -> bool
|
||
|
{
|
||
|
match $name::from_value(val)
|
||
|
{
|
||
|
Some(_) =>
|
||
|
{
|
||
|
true
|
||
|
}
|
||
|
|
||
|
None =>
|
||
|
{
|
||
|
false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Turn an enum variant into a value.
|
||
|
pub fn to_value(&self) -> $fieldType
|
||
|
{
|
||
|
match *self
|
||
|
{
|
||
|
$($name::$variant => {$value})*
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Get a str representation of this variant.
|
||
|
pub fn to_str(&self) -> &'static str
|
||
|
{
|
||
|
match *self
|
||
|
{
|
||
|
$($name::$variant => {stringify!($variant)})*
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ::std::fmt::Debug for $name
|
||
|
{
|
||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
|
||
|
{
|
||
|
write!(f, "{}", self.to_str())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ::std::fmt::Display for $name
|
||
|
{
|
||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
|
||
|
{
|
||
|
write!(f, "{}", self.to_str())
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|