bit-flags 0.1.2

provides an easy-to-use Flags trait that makes custom bitflag enums easier to implement in Rust
Documentation
#![no_std]

//! Allows for the easy creation of bitflag-based enums through the use of an easy-to-use [`Flags`]
//! trait that is auto-implemented on all types that are capable of stable bit-twiddling.
//!
//! The [`Flags`] trait is auto-implemented mplemented on types that are capable of bitwise
//! twiddling as a way of turning on and off different bit-specific flags, such as [`u8`],
//! [`u16`], [`u32`], [`u64`], etc.
//!
//! To integrate with [`Flags`], custom enum types should implent [`From<T>`] where `T` is the
//! type that implements [`Flags`]. You can then call `has_flag`, `set_flag`, and `unset_flag`
//! on `T` using flags defined by the custom enum type, like so:
//!
//! ```
//!  use bit_flags::Flags;
//!
//!  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
//!  enum MyFlags {
//!      Flag1 = 1 << 0, // 0b00000001
//!      Flag2 = 1 << 1, // 0b00000010
//!      Flag3 = 1 << 2, // 0b00000100
//!      Flag4 = 1 << 3, // 0b00001000
//!  }
//!
//!  impl From<MyFlags> for u8 {
//!      fn from(flag: MyFlags) -> Self {
//!          flag as u8
//!      }
//!  }
//!
//!  let mut flags: u8 = MyFlags::Flag1 as u8 | MyFlags::Flag2 as u8;
//!  assert!(flags.has_flag(MyFlags::Flag1));
//!  assert!(flags.has_flag(MyFlags::Flag2));
//!  assert!(!flags.has_flag(MyFlags::Flag3));
//!  flags.set_flag(MyFlags::Flag3);
//!  assert!(flags.has_flag(MyFlags::Flag3));
//!  flags.set_flag(MyFlags::Flag1);
//!  assert!(flags.has_flag(MyFlags::Flag1));
//!  flags.unset_flag(MyFlags::Flag2);
//!  assert!(!flags.has_flag(MyFlags::Flag2));
//!
//!  // You can also use the flags directly with bitwise operations:
//!  flags |= MyFlags::Flag4 as u8; // Set Flag4
//!  flags &= !(MyFlags::Flag1 as u8); // Unset Flag1
//!  assert!(flags.has_flag(MyFlags::Flag4));
//!  assert!(!flags.has_flag(MyFlags::Flag1));
//!  assert!(flags.has_flag(MyFlags::Flag3));
//!  assert!(!flags.has_flag(MyFlags::Flag2));
//! ```
//!
//! You can also use multi-byte flags:
//! ```
//!  use bit_flags::Flags;
//!
//!  #[repr(u16)]
//!  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
//!  enum MyFlags {
//!      Flag1 = 1 << 0,   // 0b0000000000000001
//!      Flag2 = 1 << 1,   // 0b0000000000000010
//!      Flag3 = 1 << 2,   // 0b0000000000000100
//!      Flag4 = 1 << 3,   // 0b0000000000001000
//!      Flag5 = 1 << 4,   // 0b0000000000010000
//!      Flag6 = 1 << 5,   // 0b0000000000100000
//!      Flag7 = 1 << 6,   // 0b0000000001000000
//!      Flag8 = 1 << 7,   // 0b0000000010000000
//!      Flag9 = 1 << 8,   // 0b0000000100000000
//!      Flag10 = 1 << 9,  // 0b0000001000000000
//!      Flag11 = 1 << 10, // 0b0000010000000000
//!      Flag12 = 1 << 11, // 0b0000100000000000
//!      Flag13 = 1 << 12, // 0b0001000000000000
//!      Flag14 = 1 << 13, // 0b0010000000000000
//!      Flag15 = 1 << 14, // 0b0100000000000000
//!      Flag16 = 1 << 15, // 0b1000000000000000
//!  }
//!
//!  impl From<MyFlags> for u16 {
//!     fn from(flag: MyFlags) -> Self {
//!         flag as u16
//!     }
//!  }
//!
//!  let mut flags: u16 = MyFlags::Flag1 as u16 | MyFlags::Flag2 as u16;
//!  assert!(flags.has_flag(MyFlags::Flag1));
//!  assert!(flags.has_flag(MyFlags::Flag2));
//!  assert!(!flags.has_flag(MyFlags::Flag3));
//!
//!  flags.set_flag(MyFlags::Flag15);
//!  assert!(flags.has_flag(MyFlags::Flag15));
//!  flags.unset_flag(MyFlags::Flag1);
//!  assert!(!flags.has_flag(MyFlags::Flag1));
//!  assert_eq!(flags, MyFlags::Flag2 as u16 | MyFlags::Flag15 as u16);
//! ```

use core::fmt::Debug;
use core::ops::*;

/// Implemented on types that are capable of bitwise twiddling as a way of turning on and off
/// different bit-specific flags, such as [`u8`], [`u16`], [`u32`], [`u64`], etc.
///
/// To integrate with [`Flags`], custom enum types should implent [`From<T>`] where `T` is the
/// type that implements [`Flags`]. You can then call `has_flag`, `set_flag`, and `unset_flag`
/// on `T` using flags defined by the custom enum type, like so:
///
/// ```
///  use bit_flags::Flags;
///
///  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
///  enum MyFlags {
///      Flag1 = 1 << 0, // 0b00000001
///      Flag2 = 1 << 1, // 0b00000010
///      Flag3 = 1 << 2, // 0b00000100
///      Flag4 = 1 << 3, // 0b00001000
///  }
///
///  impl From<MyFlags> for u8 {
///      fn from(flag: MyFlags) -> Self {
///          flag as u8
///      }
///  }
///
///  let mut flags: u8 = MyFlags::Flag1 as u8 | MyFlags::Flag2 as u8;
///  assert!(flags.has_flag(MyFlags::Flag1));
///  assert!(flags.has_flag(MyFlags::Flag2));
///  assert!(!flags.has_flag(MyFlags::Flag3));
///  flags.set_flag(MyFlags::Flag3);
///  assert!(flags.has_flag(MyFlags::Flag3));
///  flags.set_flag(MyFlags::Flag1);
///  assert!(flags.has_flag(MyFlags::Flag1));
///  flags.unset_flag(MyFlags::Flag2);
///  assert!(!flags.has_flag(MyFlags::Flag2));
///
///  // You can also use the flags directly with bitwise operations:
///  flags |= MyFlags::Flag4 as u8; // Set Flag4
///  flags &= !(MyFlags::Flag1 as u8); // Unset Flag1
///  assert!(flags.has_flag(MyFlags::Flag4));
///  assert!(!flags.has_flag(MyFlags::Flag1));
///  assert!(flags.has_flag(MyFlags::Flag3));
///  assert!(!flags.has_flag(MyFlags::Flag2));
/// ```
///
/// You can also use multi-byte flags:
/// ```
///  use bit_flags::Flags;
///
/// #[repr(u16)]
///  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
///  enum MyFlags {
///      Flag1 = 1 << 0,   // 0b0000000000000001
///      Flag2 = 1 << 1,   // 0b0000000000000010
///      Flag3 = 1 << 2,   // 0b0000000000000100
///      Flag4 = 1 << 3,   // 0b0000000000001000
///      Flag5 = 1 << 4,   // 0b0000000000010000
///      Flag6 = 1 << 5,   // 0b0000000000100000
///      Flag7 = 1 << 6,   // 0b0000000001000000
///      Flag8 = 1 << 7,   // 0b0000000010000000
///      Flag9 = 1 << 8,   // 0b0000000100000000
///      Flag10 = 1 << 9,  // 0b0000001000000000
///      Flag11 = 1 << 10, // 0b0000010000000000
///      Flag12 = 1 << 11, // 0b0000100000000000
///      Flag13 = 1 << 12, // 0b0001000000000000
///      Flag14 = 1 << 13, // 0b0010000000000000
///      Flag15 = 1 << 14, // 0b0100000000000000
///      Flag16 = 1 << 15, // 0b1000000000000000
///  }
///
///  impl From<MyFlags> for u16 {
///     fn from(flag: MyFlags) -> Self {
///         flag as u16
///     }
///  }
///
///  let mut flags: u16 = MyFlags::Flag1 as u16 | MyFlags::Flag2 as u16;
///  assert!(flags.has_flag(MyFlags::Flag1));
///  assert!(flags.has_flag(MyFlags::Flag2));
///  assert!(!flags.has_flag(MyFlags::Flag3));
///
///  flags.set_flag(MyFlags::Flag15);
///  assert!(flags.has_flag(MyFlags::Flag15));
///  flags.unset_flag(MyFlags::Flag1);
///  assert!(!flags.has_flag(MyFlags::Flag1));
///  assert_eq!(flags, MyFlags::Flag2 as u16 | MyFlags::Flag15 as u16);
/// ```
pub trait Flags<T: Into<Self>>:
    Copy
    + Clone
    + Debug
    + Send
    + Sync
    + 'static
    + PartialEq
    + Eq
    + BitAnd
    + BitOr
    + BitXor
    + BitAndAssign
    + BitOrAssign
    + BitXorAssign
    + Not
where
    <Self as BitAnd>::Output: PartialEq<Self> + Eq + Into<Self>,
    <Self as BitOr>::Output: PartialEq<Self> + Eq + Into<Self>,
    <Self as BitXor>::Output: PartialEq<Self> + Eq + Into<Self>,
    <Self as Not>::Output: Into<Self>,
{
    // Checks whether the specified flag is set on this flag set.
    #[inline(always)]
    fn has_flag(&self, flag: T) -> bool {
        let flag: Self = flag.into();
        (*self & flag) == flag
    }

    /// Sets the specified flag on this flag set.
    #[inline(always)]
    fn set_flag(&mut self, flag: T) {
        let flag: Self = flag.into();
        (*self) = ((*self) | flag).into();
    }

    /// Unsets the specified flag on this flag set.
    #[inline(always)]
    fn unset_flag(&mut self, flag: T) {
        let flag: Self = flag.into();
        (*self) = ((*self) & (!flag).into()).into();
    }
}

impl<T, U> Flags<T> for U
where
    U: Copy
        + Clone
        + Debug
        + Send
        + Sync
        + 'static
        + PartialEq
        + Eq
        + BitAnd<Output = U>
        + BitOr<Output = U>
        + BitXor<Output = U>
        + BitAndAssign
        + BitOrAssign
        + BitXorAssign
        + Not<Output = U>
        + From<T>,
    T: Into<U> + Copy,
{
}

#[test]
fn test_flags() {
    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
    enum MyFlags {
        Flag1 = 1 << 0,
        Flag2 = 1 << 1,
        Flag3 = 1 << 2,
    }

    impl From<MyFlags> for u8 {
        fn from(flag: MyFlags) -> Self {
            flag as u8
        }
    }

    let mut flags = MyFlags::Flag1 as u8 | MyFlags::Flag2 as u8;

    assert!(flags.has_flag(MyFlags::Flag1));
    assert!(flags.has_flag(MyFlags::Flag2));
    assert!(!flags.has_flag(MyFlags::Flag3));

    flags.set_flag(MyFlags::Flag3);
    assert!(flags.has_flag(MyFlags::Flag3));

    flags.set_flag(MyFlags::Flag1);
    assert!(flags.has_flag(MyFlags::Flag1));

    flags.unset_flag(MyFlags::Flag2);
    assert!(!flags.has_flag(MyFlags::Flag2));
}