89 lines
2.4 KiB
Rust
89 lines
2.4 KiB
Rust
#![doc(hidden)]
|
|
|
|
/// A wrapper for `bitflags!` which adds a `FromStr` implementation.
|
|
#[macro_export]
|
|
macro_rules! c_bitfield
|
|
{
|
|
(
|
|
$(#[$outer:meta])*
|
|
pub struct $t:ident: $ti:ty {
|
|
$(
|
|
$(#[$inner:ident $($args:tt)*])*
|
|
$f:ident = $v:expr
|
|
),+
|
|
$(,)?
|
|
}
|
|
) => {
|
|
bitflags! {
|
|
$(#[$outer])*
|
|
pub struct $t: $ti {
|
|
$(
|
|
$(#[$inner $($args)*])*
|
|
const $f = 1 << $v;
|
|
)+
|
|
}
|
|
}
|
|
|
|
#[allow(unused_qualifications)]
|
|
impl std::str::FromStr for $t
|
|
{
|
|
type Err = $crate::err::ParseFlagError;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err>
|
|
{
|
|
let mut flags = $t::empty();
|
|
|
|
for s in s.split('|') {
|
|
match s {
|
|
$(
|
|
stringify!($f) => flags.insert($t::$f),
|
|
)+
|
|
"(none)" => (),
|
|
_ => return Err(Self::Err::new(stringify!($t)))
|
|
}
|
|
}
|
|
|
|
Ok(flags)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test
|
|
{
|
|
use crate::err::ParseFlagError;
|
|
use std::str::FromStr;
|
|
|
|
c_bitfield! {
|
|
pub struct TestFlag: u16 {
|
|
ZERO = 0,
|
|
ONE = 1,
|
|
TWO = 2,
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn c_bitfield()
|
|
{
|
|
assert_eq!(TestFlag::from_bits(0), Some(TestFlag::empty()));
|
|
assert_eq!(TestFlag::from_bits(1), Some(TestFlag::ZERO));
|
|
assert_eq!(TestFlag::from_bits(2), Some(TestFlag::ONE));
|
|
assert_eq!(TestFlag::from_bits(4), Some(TestFlag::TWO));
|
|
assert_eq!(TestFlag::from_bits(8), None);
|
|
assert_eq!(TestFlag::from_str("(none)"), Ok(TestFlag::empty()));
|
|
assert_eq!(TestFlag::from_str("ZERO"), Ok(TestFlag::ZERO));
|
|
assert_eq!(TestFlag::from_str("ONE"), Ok(TestFlag::ONE));
|
|
assert_eq!(TestFlag::from_str("TWO"), Ok(TestFlag::TWO));
|
|
assert_eq!(TestFlag::from_str("ZERO|ONE|TWO"), Ok(TestFlag::all()));
|
|
assert_eq!(TestFlag::from_str("TWO|ZERO|ONE"), Ok(TestFlag::all()));
|
|
assert_eq!(TestFlag::from_str("ONE|ONE|ONE"), Ok(TestFlag::ONE));
|
|
assert_eq!(TestFlag::from_str("(none)|(none)"), Ok(TestFlag::empty()));
|
|
assert_eq!(TestFlag::from_str("(none)|ONE"), Ok(TestFlag::ONE));
|
|
assert_eq!(TestFlag::from_str("THREE"),
|
|
Err(ParseFlagError::new("TestFlag")));
|
|
}
|
|
}
|
|
|
|
// EOF
|