Custom

Define and operate on a type represented as a bitfield

bitflags bitflags-crates.io bitflags-github bitflags-lib.rs cat-no-std

bitflags offers a macro to generate structures which behave like bitflags. It creates type-safe bitfield type MyFlags with help of bitflags::bitflags⮳ macro and implements elementary clear operation as well as std::fmt::Display⮳ trait for it. Subsequently, shows basic bitwise operations and formatting.

use std::fmt;

use bitflags::bitflags;

bitflags! {
    // Attributes can be applied to flags types
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
    struct MyFlags: u32 {
        const FLAG_A       = 0b0000_0001;
        const FLAG_B       = 0b0000_0010;
        const FLAG_C       = 0b0000_0100;
        const FLAG_ABC     = Self::FLAG_A.bits()
                           | Self::FLAG_B.bits()
                           | Self::FLAG_C.bits();
    }
}

impl MyFlags {
    pub fn as_u64(&self) -> u64 {
        self.bits() as u64
    }
}

impl fmt::Display for MyFlags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:032b}", self.bits())
    }
}

fn main() {
    let e1 = MyFlags::FLAG_A | MyFlags::FLAG_C;
    let e2 = MyFlags::FLAG_B | MyFlags::FLAG_C;
    assert_eq!((e1 | e2), MyFlags::FLAG_ABC);
    assert_eq!((e1 & e2), MyFlags::FLAG_C);
    assert_eq!((e1 - e2), MyFlags::FLAG_A);
    assert_eq!(!e2, MyFlags::FLAG_A);
    // Use the fmt::Display implementation above
    println!("e1: {} e2: {}", e1, e2);

    let flags = MyFlags::FLAG_ABC;
    assert_eq!(format!("{}", flags), "00000000000000000000000000000111");
    assert_eq!(format!("{:?}", MyFlags::FLAG_B), "MyFlags(FLAG_B)");
    assert_eq!(
        format!("{:?}", MyFlags::FLAG_A | MyFlags::FLAG_B),
        "MyFlags(FLAG_A | FLAG_B)"
    );
    println!("{:?}", flags);
}

flagset

flagset flagset-crates.io flagset-github flagset-lib.rs

FlagSet is a new, ergonomic approach to handling flags that combines the best of existing crates like bitflags and enumflags without their downsides.

use std::os::raw::c_int;

use flagset::flags;

flags! {
    enum FlagsA: u8 {
        Foo,
        Bar,
        Baz,
    }

    enum FlagsB: c_int {
        Foo,
        Bar,
        Baz,
    }
}

fn main() {}