bit_flags/
lib.rs

1#![no_std]
2
3//! Allows for the easy creation of bitflag-based enums through the use of an easy-to-use [`Flags`]
4//! trait that is auto-implemented on all types that are capable of stable bit-twiddling.
5//!
6//! The [`Flags`] trait is auto-implemented mplemented on types that are capable of bitwise
7//! twiddling as a way of turning on and off different bit-specific flags, such as [`u8`],
8//! [`u16`], [`u32`], [`u64`], etc.
9//!
10//! To integrate with [`Flags`], custom enum types should implent [`From<T>`] where `T` is the
11//! type that implements [`Flags`]. You can then call `has_flag`, `set_flag`, and `unset_flag`
12//! on `T` using flags defined by the custom enum type, like so:
13//!
14//! ```
15//!  use bit_flags::Flags;
16//!
17//!  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
18//!  enum MyFlags {
19//!      Flag1 = 1 << 0, // 0b00000001
20//!      Flag2 = 1 << 1, // 0b00000010
21//!      Flag3 = 1 << 2, // 0b00000100
22//!      Flag4 = 1 << 3, // 0b00001000
23//!  }
24//!
25//!  impl From<MyFlags> for u8 {
26//!      fn from(flag: MyFlags) -> Self {
27//!          flag as u8
28//!      }
29//!  }
30//!
31//!  let mut flags: u8 = MyFlags::Flag1 as u8 | MyFlags::Flag2 as u8;
32//!  assert!(flags.has_flag(MyFlags::Flag1));
33//!  assert!(flags.has_flag(MyFlags::Flag2));
34//!  assert!(!flags.has_flag(MyFlags::Flag3));
35//!  flags.set_flag(MyFlags::Flag3);
36//!  assert!(flags.has_flag(MyFlags::Flag3));
37//!  flags.set_flag(MyFlags::Flag1);
38//!  assert!(flags.has_flag(MyFlags::Flag1));
39//!  flags.unset_flag(MyFlags::Flag2);
40//!  assert!(!flags.has_flag(MyFlags::Flag2));
41//!
42//!  // You can also use the flags directly with bitwise operations:
43//!  flags |= MyFlags::Flag4 as u8; // Set Flag4
44//!  flags &= !(MyFlags::Flag1 as u8); // Unset Flag1
45//!  assert!(flags.has_flag(MyFlags::Flag4));
46//!  assert!(!flags.has_flag(MyFlags::Flag1));
47//!  assert!(flags.has_flag(MyFlags::Flag3));
48//!  assert!(!flags.has_flag(MyFlags::Flag2));
49//! ```
50//!
51//! You can also use multi-byte flags:
52//! ```
53//!  use bit_flags::Flags;
54//!
55//!  #[repr(u16)]
56//!  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
57//!  enum MyFlags {
58//!      Flag1 = 1 << 0,   // 0b0000000000000001
59//!      Flag2 = 1 << 1,   // 0b0000000000000010
60//!      Flag3 = 1 << 2,   // 0b0000000000000100
61//!      Flag4 = 1 << 3,   // 0b0000000000001000
62//!      Flag5 = 1 << 4,   // 0b0000000000010000
63//!      Flag6 = 1 << 5,   // 0b0000000000100000
64//!      Flag7 = 1 << 6,   // 0b0000000001000000
65//!      Flag8 = 1 << 7,   // 0b0000000010000000
66//!      Flag9 = 1 << 8,   // 0b0000000100000000
67//!      Flag10 = 1 << 9,  // 0b0000001000000000
68//!      Flag11 = 1 << 10, // 0b0000010000000000
69//!      Flag12 = 1 << 11, // 0b0000100000000000
70//!      Flag13 = 1 << 12, // 0b0001000000000000
71//!      Flag14 = 1 << 13, // 0b0010000000000000
72//!      Flag15 = 1 << 14, // 0b0100000000000000
73//!      Flag16 = 1 << 15, // 0b1000000000000000
74//!  }
75//!
76//!  impl From<MyFlags> for u16 {
77//!     fn from(flag: MyFlags) -> Self {
78//!         flag as u16
79//!     }
80//!  }
81//!
82//!  let mut flags: u16 = MyFlags::Flag1 as u16 | MyFlags::Flag2 as u16;
83//!  assert!(flags.has_flag(MyFlags::Flag1));
84//!  assert!(flags.has_flag(MyFlags::Flag2));
85//!  assert!(!flags.has_flag(MyFlags::Flag3));
86//!
87//!  flags.set_flag(MyFlags::Flag15);
88//!  assert!(flags.has_flag(MyFlags::Flag15));
89//!  flags.unset_flag(MyFlags::Flag1);
90//!  assert!(!flags.has_flag(MyFlags::Flag1));
91//!  assert_eq!(flags, MyFlags::Flag2 as u16 | MyFlags::Flag15 as u16);
92//! ```
93
94use core::fmt::Debug;
95use core::ops::*;
96
97/// Implemented on types that are capable of bitwise twiddling as a way of turning on and off
98/// different bit-specific flags, such as [`u8`], [`u16`], [`u32`], [`u64`], etc.
99///
100/// To integrate with [`Flags`], custom enum types should implent [`From<T>`] where `T` is the
101/// type that implements [`Flags`]. You can then call `has_flag`, `set_flag`, and `unset_flag`
102/// on `T` using flags defined by the custom enum type, like so:
103///
104/// ```
105///  use bit_flags::Flags;
106///
107///  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
108///  enum MyFlags {
109///      Flag1 = 1 << 0, // 0b00000001
110///      Flag2 = 1 << 1, // 0b00000010
111///      Flag3 = 1 << 2, // 0b00000100
112///      Flag4 = 1 << 3, // 0b00001000
113///  }
114///
115///  impl From<MyFlags> for u8 {
116///      fn from(flag: MyFlags) -> Self {
117///          flag as u8
118///      }
119///  }
120///
121///  let mut flags: u8 = MyFlags::Flag1 as u8 | MyFlags::Flag2 as u8;
122///  assert!(flags.has_flag(MyFlags::Flag1));
123///  assert!(flags.has_flag(MyFlags::Flag2));
124///  assert!(!flags.has_flag(MyFlags::Flag3));
125///  flags.set_flag(MyFlags::Flag3);
126///  assert!(flags.has_flag(MyFlags::Flag3));
127///  flags.set_flag(MyFlags::Flag1);
128///  assert!(flags.has_flag(MyFlags::Flag1));
129///  flags.unset_flag(MyFlags::Flag2);
130///  assert!(!flags.has_flag(MyFlags::Flag2));
131///
132///  // You can also use the flags directly with bitwise operations:
133///  flags |= MyFlags::Flag4 as u8; // Set Flag4
134///  flags &= !(MyFlags::Flag1 as u8); // Unset Flag1
135///  assert!(flags.has_flag(MyFlags::Flag4));
136///  assert!(!flags.has_flag(MyFlags::Flag1));
137///  assert!(flags.has_flag(MyFlags::Flag3));
138///  assert!(!flags.has_flag(MyFlags::Flag2));
139/// ```
140///
141/// You can also use multi-byte flags:
142/// ```
143///  use bit_flags::Flags;
144///
145/// #[repr(u16)]
146///  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
147///  enum MyFlags {
148///      Flag1 = 1 << 0,   // 0b0000000000000001
149///      Flag2 = 1 << 1,   // 0b0000000000000010
150///      Flag3 = 1 << 2,   // 0b0000000000000100
151///      Flag4 = 1 << 3,   // 0b0000000000001000
152///      Flag5 = 1 << 4,   // 0b0000000000010000
153///      Flag6 = 1 << 5,   // 0b0000000000100000
154///      Flag7 = 1 << 6,   // 0b0000000001000000
155///      Flag8 = 1 << 7,   // 0b0000000010000000
156///      Flag9 = 1 << 8,   // 0b0000000100000000
157///      Flag10 = 1 << 9,  // 0b0000001000000000
158///      Flag11 = 1 << 10, // 0b0000010000000000
159///      Flag12 = 1 << 11, // 0b0000100000000000
160///      Flag13 = 1 << 12, // 0b0001000000000000
161///      Flag14 = 1 << 13, // 0b0010000000000000
162///      Flag15 = 1 << 14, // 0b0100000000000000
163///      Flag16 = 1 << 15, // 0b1000000000000000
164///  }
165///
166///  impl From<MyFlags> for u16 {
167///     fn from(flag: MyFlags) -> Self {
168///         flag as u16
169///     }
170///  }
171///
172///  let mut flags: u16 = MyFlags::Flag1 as u16 | MyFlags::Flag2 as u16;
173///  assert!(flags.has_flag(MyFlags::Flag1));
174///  assert!(flags.has_flag(MyFlags::Flag2));
175///  assert!(!flags.has_flag(MyFlags::Flag3));
176///
177///  flags.set_flag(MyFlags::Flag15);
178///  assert!(flags.has_flag(MyFlags::Flag15));
179///  flags.unset_flag(MyFlags::Flag1);
180///  assert!(!flags.has_flag(MyFlags::Flag1));
181///  assert_eq!(flags, MyFlags::Flag2 as u16 | MyFlags::Flag15 as u16);
182/// ```
183pub trait Flags<T: Into<Self>>:
184    Copy
185    + Clone
186    + Debug
187    + Send
188    + Sync
189    + 'static
190    + PartialEq
191    + Eq
192    + BitAnd
193    + BitOr
194    + BitXor
195    + BitAndAssign
196    + BitOrAssign
197    + BitXorAssign
198    + Not
199where
200    <Self as BitAnd>::Output: PartialEq<Self> + Eq + Into<Self>,
201    <Self as BitOr>::Output: PartialEq<Self> + Eq + Into<Self>,
202    <Self as BitXor>::Output: PartialEq<Self> + Eq + Into<Self>,
203    <Self as Not>::Output: Into<Self>,
204{
205    // Checks whether the specified flag is set on this flag set.
206    #[inline(always)]
207    fn has_flag(&self, flag: T) -> bool {
208        let flag: Self = flag.into();
209        (*self & flag) == flag
210    }
211
212    /// Sets the specified flag on this flag set.
213    #[inline(always)]
214    fn set_flag(&mut self, flag: T) {
215        let flag: Self = flag.into();
216        (*self) = ((*self) | flag).into();
217    }
218
219    /// Unsets the specified flag on this flag set.
220    #[inline(always)]
221    fn unset_flag(&mut self, flag: T) {
222        let flag: Self = flag.into();
223        (*self) = ((*self) & (!flag).into()).into();
224    }
225}
226
227impl<T, U> Flags<T> for U
228where
229    U: Copy
230        + Clone
231        + Debug
232        + Send
233        + Sync
234        + 'static
235        + PartialEq
236        + Eq
237        + BitAnd<Output = U>
238        + BitOr<Output = U>
239        + BitXor<Output = U>
240        + BitAndAssign
241        + BitOrAssign
242        + BitXorAssign
243        + Not<Output = U>
244        + From<T>,
245    T: Into<U> + Copy,
246{
247}
248
249#[test]
250fn test_flags() {
251    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
252    enum MyFlags {
253        Flag1 = 1 << 0,
254        Flag2 = 1 << 1,
255        Flag3 = 1 << 2,
256    }
257
258    impl From<MyFlags> for u8 {
259        fn from(flag: MyFlags) -> Self {
260            flag as u8
261        }
262    }
263
264    let mut flags = MyFlags::Flag1 as u8 | MyFlags::Flag2 as u8;
265
266    assert!(flags.has_flag(MyFlags::Flag1));
267    assert!(flags.has_flag(MyFlags::Flag2));
268    assert!(!flags.has_flag(MyFlags::Flag3));
269
270    flags.set_flag(MyFlags::Flag3);
271    assert!(flags.has_flag(MyFlags::Flag3));
272
273    flags.set_flag(MyFlags::Flag1);
274    assert!(flags.has_flag(MyFlags::Flag1));
275
276    flags.unset_flag(MyFlags::Flag2);
277    assert!(!flags.has_flag(MyFlags::Flag2));
278}