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}