• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 Red Hat, Inc.
3 //
4 // Author: Nathaniel McCallum <npmccallum@redhat.com>
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 //
10 //     http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
18 
19 //! # Welcome to FlagSet!
20 //!
21 //! FlagSet is a new, ergonomic approach to handling flags that combines the
22 //! best of existing crates like `bitflags` and `enumflags` without their
23 //! downsides.
24 //!
25 //! ## Existing Implementations
26 //!
27 //! The `bitflags` crate has long been part of the Rust ecosystem.
28 //! Unfortunately, it doesn't feel like natural Rust. The `bitflags` crate
29 //! uses a wierd struct format to define flags. Flags themselves are just
30 //! integers constants, so there is little type-safety involved. But it doesn't
31 //! have any dependencies. It also allows you to define implied flags (otherwise
32 //! known as overlapping flags).
33 //!
34 //! The `enumflags` crate tried to improve on `bitflags` by using enumerations
35 //! to define flags. This was a big improvement to the natural feel of the code.
36 //! Unfortunately, there are some design flaws. To generate the flags,
37 //! procedural macros were used. This implied two separate crates plus
38 //! additional dependencies. Further, `enumflags` specifies the size of the
39 //! flags using a `repr($size)` attribute. Unfortunately, this attribute
40 //! cannot resolve type aliases, such as `c_int`. This makes `enumflags` a
41 //! poor fit for FFI, which is the most important place for a flags library.
42 //! The `enumflags` crate also disallows overlapping flags and is not
43 //! maintained.
44 //!
45 //! FlagSet improves on both of these by adopting the `enumflags` natural feel
46 //! and the `bitflags` mode of flag generation; as well as additional API usage
47 //! niceties. FlagSet has no dependencies and is extensively documented and
48 //! tested. It also tries very hard to prevent you from making mistakes by
49 //! avoiding external usage of the integer types. FlagSet is also a zero-cost
50 //! abstraction: all functions are inlineable and should reduce to the core
51 //! integer operations. FlagSet also does not depend on stdlib, so it can be
52 //! used in `no_std` libraries and applications.
53 //!
54 //! ## Defining Flags
55 //!
56 //! Flags are defined using the `flags!` macro:
57 //!
58 //! ```
59 //! use flagset::{FlagSet, flags};
60 //! use std::os::raw::c_int;
61 //!
62 //! flags! {
63 //!     enum FlagsA: u8 {
64 //!         Foo,
65 //!         Bar,
66 //!         Baz,
67 //!     }
68 //!
69 //!     enum FlagsB: c_int {
70 //!         Foo,
71 //!         Bar,
72 //!         Baz,
73 //!     }
74 //! }
75 //! ```
76 //!
77 //! Notice that a flag definition looks just like a regular enumeration, with
78 //! the addition of the field-size type. The field-size type is required and
79 //! can be either a type or a type alias. Both examples are given above.
80 //!
81 //! Also note that the field-size type specifies the size of the corresponding
82 //! `FlagSet` type, not size of the enumeration itself. To specify the size of
83 //! the enumeration, use the `repr($size)` attribute as specified below.
84 //!
85 //! ## Flag Values
86 //!
87 //! Flags often need values assigned to them. This can be done implicitly,
88 //! where the value depends on the order of the flags:
89 //!
90 //! ```
91 //! use flagset::{FlagSet, flags};
92 //!
93 //! flags! {
94 //!     enum Flags: u16 {
95 //!         Foo, // Implicit Value: 0b0001
96 //!         Bar, // Implicit Value: 0b0010
97 //!         Baz, // Implicit Value: 0b0100
98 //!     }
99 //! }
100 //! ```
101 //!
102 //! Alternatively, flag values can be defined explicitly, by specifying any
103 //! `const` expression:
104 //!
105 //! ```
106 //! use flagset::{FlagSet, flags};
107 //!
108 //! flags! {
109 //!     enum Flags: u16 {
110 //!         Foo = 0x01,   // Explicit Value: 0b0001
111 //!         Bar = 2,      // Explicit Value: 0b0010
112 //!         Baz = 0b0100, // Explicit Value: 0b0100
113 //!     }
114 //! }
115 //! ```
116 //!
117 //! Flags can also overlap or "imply" other flags:
118 //!
119 //! ```
120 //! use flagset::{FlagSet, flags};
121 //!
122 //! flags! {
123 //!     enum Flags: u16 {
124 //!         Foo = 0b0001,
125 //!         Bar = 0b0010,
126 //!         Baz = 0b0110, // Implies Bar
127 //!         All = (Flags::Foo | Flags::Bar | Flags::Baz).bits(),
128 //!     }
129 //! }
130 //! ```
131 //!
132 //! ## Specifying Attributes
133 //!
134 //! Attributes can be used on the enumeration itself or any of the values:
135 //!
136 //! ```
137 //! use flagset::{FlagSet, flags};
138 //!
139 //! flags! {
140 //!     #[derive(PartialOrd, Ord)]
141 //!     enum Flags: u8 {
142 //!         Foo,
143 //!         #[deprecated]
144 //!         Bar,
145 //!         Baz,
146 //!     }
147 //! }
148 //! ```
149 //!
150 //! ## Collections of Flags
151 //!
152 //! A collection of flags is a `FlagSet<T>`. If you are storing the flags in
153 //! memory, the raw `FlagSet<T>` type should be used. However, if you want to
154 //! receive flags as an input to a function, you should use
155 //! `impl Into<FlagSet<T>>`. This allows for very ergonomic APIs:
156 //!
157 //! ```
158 //! use flagset::{FlagSet, flags};
159 //!
160 //! flags! {
161 //!     enum Flags: u8 {
162 //!         Foo,
163 //!         Bar,
164 //!         Baz,
165 //!     }
166 //! }
167 //!
168 //! struct Container(FlagSet<Flags>);
169 //!
170 //! impl Container {
171 //!     fn new(flags: impl Into<FlagSet<Flags>>) -> Container {
172 //!         Container(flags.into())
173 //!     }
174 //! }
175 //!
176 //! assert_eq!(Container::new(Flags::Foo | Flags::Bar).0.bits(), 0b011);
177 //! assert_eq!(Container::new(Flags::Foo).0.bits(), 0b001);
178 //! assert_eq!(Container::new(None).0.bits(), 0b000);
179 //! ```
180 //!
181 //! ## Operations
182 //!
183 //! Operations can be performed on a `FlagSet<F>` or on individual flags:
184 //!
185 //! | Operator | Assignment Operator | Meaning                |
186 //! |----------|---------------------|------------------------|
187 //! | \|       | \|=                 | Union                  |
188 //! | &        | &=                  | Intersection           |
189 //! | ^        | ^=                  | Toggle specified flags |
190 //! | -        | -=                  | Difference             |
191 //! | %        | %=                  | Symmetric difference   |
192 //! | !        |                     | Toggle all flags       |
193 //!
194 #![cfg_attr(
195     feature = "serde",
196     doc = r#"
197 
198 ## Optional Serde support
199 
200 [Serde] support can be enabled with the 'serde' feature flag. You can then serialize and
201 deserialize `FlagSet<T>` to and from any of the [supported formats]:
202 
203  ```
204  use flagset::{FlagSet, flags};
205 
206  flags! {
207      enum Flags: u8 {
208          Foo,
209          Bar,
210      }
211  }
212 
213  let flagset = Flags::Foo | Flags::Bar;
214  let json = serde_json::to_string(&flagset).unwrap();
215  let flagset: FlagSet<Flags> = serde_json::from_str(&json).unwrap();
216  assert_eq!(flagset.bits(), 0b011);
217  ```
218 
219 For serialization and deserialization of flags enum itself, you can use the [`serde_repr`] crate
220 (or implement `serde::ser::Serialize` and `serde:de::Deserialize` manually), combined with the
221 appropriate `repr` attribute:
222 
223  ```
224  use flagset::{FlagSet, flags};
225  use serde_repr::{Serialize_repr, Deserialize_repr};
226 
227  flags! {
228     #[repr(u8)]
229     #[derive(Deserialize_repr, Serialize_repr)]
230     enum Flags: u8 {
231          Foo,
232          Bar,
233     }
234  }
235 
236  let json = serde_json::to_string(&Flags::Foo).unwrap();
237  let flag: Flags = serde_json::from_str(&json).unwrap();
238  assert_eq!(flag, Flags::Foo);
239  ```
240 
241 [Serde]: https://serde.rs/
242 [supported formats]: https://serde.rs/#data-formats
243 [`serde_repr`]: https://crates.io/crates/serde_repr
244 "#
245 )]
246 #![allow(unknown_lints)]
247 #![warn(clippy::all)]
248 #![no_std]
249 
250 /// Local Android change: Use std to allow building as a dylib.
251 #[cfg(android_dylib)]
252 extern crate std;
253 
254 use core::fmt::{Debug, Formatter, Result};
255 use core::ops::*;
256 
257 /// Error type returned when creating a new flagset from bits is invalid or undefined.
258 /// ```
259 /// use flagset::{FlagSet, flags};
260 ///
261 /// flags! {
262 ///     pub enum Flag: u16 {
263 ///         Foo = 0b0001,
264 ///         Bar = 0b0010,
265 ///         Baz = 0b0100,
266 ///         Qux = 0b1010, // Implies Bar
267 ///     }
268 /// }
269 ///
270 /// assert_eq!(FlagSet::<Flag>::new(0b01101), Err(flagset::InvalidBits)); // Invalid
271 /// assert_eq!(FlagSet::<Flag>::new(0b10101), Err(flagset::InvalidBits)); // Unknown
272 /// ```
273 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
274 pub struct InvalidBits;
275 
276 impl core::fmt::Display for InvalidBits {
277     #[inline]
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result278     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
279         write!(f, "invalid bits")
280     }
281 }
282 
283 #[doc(hidden)]
284 pub trait Flags:
285     Copy
286     + Clone
287     + Debug
288     + PartialEq
289     + Eq
290     + BitAnd<Self, Output = FlagSet<Self>>
291     + BitOr<Self, Output = FlagSet<Self>>
292     + BitXor<Self, Output = FlagSet<Self>>
293     + Sub<Self, Output = FlagSet<Self>>
294     + Rem<Self, Output = FlagSet<Self>>
295     + Not<Output = FlagSet<Self>>
296     + Into<FlagSet<Self>>
297     + 'static
298 {
299     type Type: Copy
300         + Clone
301         + Debug
302         + PartialEq
303         + Eq
304         + Default
305         + BitAnd<Self::Type, Output = Self::Type>
306         + BitAndAssign<Self::Type>
307         + BitOr<Self::Type, Output = Self::Type>
308         + BitOrAssign<Self::Type>
309         + BitXor<Self::Type, Output = Self::Type>
310         + BitXorAssign<Self::Type>
311         + Not<Output = Self::Type>;
312 
313     /// A slice containing all the possible flag values.
314     const LIST: &'static [Self];
315 
316     /// Creates an empty `FlagSet` of this type
317     #[inline]
none() -> FlagSet<Self>318     fn none() -> FlagSet<Self> {
319         FlagSet::default()
320     }
321 }
322 
323 #[derive(Copy, Clone, Eq)]
324 pub struct FlagSet<F: Flags>(F::Type);
325 
326 #[doc(hidden)]
327 #[derive(Copy, Clone)]
328 pub struct Iter<F: Flags>(FlagSet<F>, usize);
329 
330 impl<F: Flags> Iterator for Iter<F> {
331     type Item = F;
332 
333     #[inline]
next(&mut self) -> Option<Self::Item>334     fn next(&mut self) -> Option<Self::Item> {
335         while self.1 < F::LIST.len() {
336             let next = F::LIST[self.1];
337             self.1 += 1;
338 
339             if self.0.contains(next) {
340                 return Some(next);
341             }
342         }
343 
344         None
345     }
346 }
347 
348 impl<F: Flags> IntoIterator for FlagSet<F> {
349     type Item = F;
350     type IntoIter = Iter<F>;
351 
352     /// Iterate over the flags in the set.
353     ///
354     /// **NOTE**: The order in which the flags are iterated is undefined.
355     ///
356     /// ```
357     /// use flagset::{FlagSet, flags};
358     ///
359     /// flags! {
360     ///     enum Flag: u8 {
361     ///         Foo = 0b001,
362     ///         Bar = 0b010,
363     ///         Baz = 0b100
364     ///     }
365     /// }
366     ///
367     /// let set = Flag::Foo | Flag::Bar;
368     /// let mut iter = set.into_iter();
369     /// assert_eq!(iter.next(), Some(Flag::Foo));
370     /// assert_eq!(iter.next(), Some(Flag::Bar));
371     /// assert_eq!(iter.next(), None);
372     /// ```
373     #[inline]
into_iter(self) -> Self::IntoIter374     fn into_iter(self) -> Self::IntoIter {
375         Iter(self, 0)
376     }
377 }
378 
379 impl<F: Flags> Debug for FlagSet<F> {
380     #[inline]
fmt(&self, f: &mut Formatter) -> Result381     fn fmt(&self, f: &mut Formatter) -> Result {
382         write!(f, "FlagSet(")?;
383         for (i, flag) in self.into_iter().enumerate() {
384             write!(f, "{}{:?}", if i > 0 { " | " } else { "" }, flag)?;
385         }
386         write!(f, ")")
387     }
388 }
389 
390 impl<F: Flags, R: Copy + Into<FlagSet<F>>> PartialEq<R> for FlagSet<F> {
391     #[inline]
eq(&self, rhs: &R) -> bool392     fn eq(&self, rhs: &R) -> bool {
393         self.0 == (*rhs).into().0
394     }
395 }
396 
397 impl<F: Flags> AsRef<F::Type> for FlagSet<F> {
398     #[inline]
as_ref(&self) -> &F::Type399     fn as_ref(&self) -> &F::Type {
400         &self.0
401     }
402 }
403 
404 impl<F: Flags> From<Option<FlagSet<F>>> for FlagSet<F> {
405     /// Converts from `Option<FlagSet<F>>` to `FlagSet<F>`.
406     ///
407     /// Most notably, this allows for the use of `None` in many places to
408     /// substitute for manually creating an empty `FlagSet<F>`. See below.
409     ///
410     /// ```
411     /// use flagset::{FlagSet, flags};
412     ///
413     /// flags! {
414     ///     enum Flag: u8 {
415     ///         Foo = 0b001,
416     ///         Bar = 0b010,
417     ///         Baz = 0b100
418     ///     }
419     /// }
420     ///
421     /// fn convert(v: impl Into<FlagSet<Flag>>) -> u8 {
422     ///     v.into().bits()
423     /// }
424     ///
425     /// assert_eq!(convert(Flag::Foo | Flag::Bar), 0b011);
426     /// assert_eq!(convert(Flag::Foo), 0b001);
427     /// assert_eq!(convert(None), 0b000);
428     /// ```
429     #[inline]
from(value: Option<FlagSet<F>>) -> FlagSet<F>430     fn from(value: Option<FlagSet<F>>) -> FlagSet<F> {
431         value.unwrap_or_default()
432     }
433 }
434 
435 impl<F: Flags> Default for FlagSet<F> {
436     /// Creates a new, empty FlagSet.
437     ///
438     /// ```
439     /// use flagset::{FlagSet, flags};
440     ///
441     /// flags! {
442     ///     enum Flag: u8 {
443     ///         Foo = 0b001,
444     ///         Bar = 0b010,
445     ///         Baz = 0b100
446     ///     }
447     /// }
448     ///
449     /// let set = FlagSet::<Flag>::default();
450     /// assert!(set.is_empty());
451     /// assert!(!set.is_full());
452     /// assert!(!set.contains(Flag::Foo));
453     /// assert!(!set.contains(Flag::Bar));
454     /// assert!(!set.contains(Flag::Baz));
455     /// ```
456     #[inline]
default() -> Self457     fn default() -> Self {
458         FlagSet(F::Type::default())
459     }
460 }
461 
462 impl<F: Flags> Not for FlagSet<F> {
463     type Output = Self;
464 
465     /// Calculates the complement of the current set.
466     ///
467     /// In common parlance, this returns the set of all possible flags that are
468     /// not in the current set.
469     ///
470     /// ```
471     /// use flagset::{FlagSet, flags};
472     ///
473     /// flags! {
474     ///     #[derive(PartialOrd, Ord)]
475     ///     enum Flag: u8 {
476     ///         Foo = 1 << 0,
477     ///         Bar = 1 << 1,
478     ///         Baz = 1 << 2
479     ///     }
480     /// }
481     ///
482     /// let set = !FlagSet::from(Flag::Foo);
483     /// assert!(!set.is_empty());
484     /// assert!(!set.is_full());
485     /// assert!(!set.contains(Flag::Foo));
486     /// assert!(set.contains(Flag::Bar));
487     /// assert!(set.contains(Flag::Baz));
488     /// ```
489     #[inline]
not(self) -> Self490     fn not(self) -> Self {
491         FlagSet(!self.0)
492     }
493 }
494 
495 impl<F: Flags, R: Into<FlagSet<F>>> BitAnd<R> for FlagSet<F> {
496     type Output = Self;
497 
498     /// Calculates the intersection of the current set and the specified flags.
499     ///
500     /// ```
501     /// use flagset::{FlagSet, flags};
502     ///
503     /// flags! {
504     ///     #[derive(PartialOrd, Ord)]
505     ///     pub enum Flag: u8 {
506     ///         Foo = 0b001,
507     ///         Bar = 0b010,
508     ///         Baz = 0b100
509     ///     }
510     /// }
511     ///
512     /// let set0 = Flag::Foo | Flag::Bar;
513     /// let set1 = Flag::Baz | Flag::Bar;
514     /// assert_eq!(set0 & set1, Flag::Bar);
515     /// assert_eq!(set0 & Flag::Foo, Flag::Foo);
516     /// assert_eq!(set1 & Flag::Baz, Flag::Baz);
517     /// ```
518     #[inline]
bitand(self, rhs: R) -> Self519     fn bitand(self, rhs: R) -> Self {
520         FlagSet(self.0 & rhs.into().0)
521     }
522 }
523 
524 impl<F: Flags, R: Into<FlagSet<F>>> BitAndAssign<R> for FlagSet<F> {
525     /// Assigns the intersection of the current set and the specified flags.
526     ///
527     /// ```
528     /// use flagset::{FlagSet, flags};
529     ///
530     /// flags! {
531     ///     enum Flag: u64 {
532     ///         Foo = 0b001,
533     ///         Bar = 0b010,
534     ///         Baz = 0b100
535     ///     }
536     /// }
537     ///
538     /// let mut set0 = Flag::Foo | Flag::Bar;
539     /// let mut set1 = Flag::Baz | Flag::Bar;
540     ///
541     /// set0 &= set1;
542     /// assert_eq!(set0, Flag::Bar);
543     ///
544     /// set1 &= Flag::Baz;
545     /// assert_eq!(set0, Flag::Bar);
546     /// ```
547     #[inline]
bitand_assign(&mut self, rhs: R)548     fn bitand_assign(&mut self, rhs: R) {
549         self.0 &= rhs.into().0
550     }
551 }
552 
553 impl<F: Flags, R: Into<FlagSet<F>>> BitOr<R> for FlagSet<F> {
554     type Output = Self;
555 
556     /// Calculates the union of the current set with the specified flags.
557     ///
558     /// ```
559     /// use flagset::{FlagSet, flags};
560     ///
561     /// flags! {
562     ///     #[derive(PartialOrd, Ord)]
563     ///     pub enum Flag: u8 {
564     ///         Foo = 0b001,
565     ///         Bar = 0b010,
566     ///         Baz = 0b100
567     ///     }
568     /// }
569     ///
570     /// let set0 = Flag::Foo | Flag::Bar;
571     /// let set1 = Flag::Baz | Flag::Bar;
572     /// assert_eq!(set0 | set1, FlagSet::full());
573     /// ```
574     #[inline]
bitor(self, rhs: R) -> Self575     fn bitor(self, rhs: R) -> Self {
576         FlagSet(self.0 | rhs.into().0)
577     }
578 }
579 
580 impl<F: Flags, R: Into<FlagSet<F>>> BitOrAssign<R> for FlagSet<F> {
581     /// Assigns the union of the current set with the specified flags.
582     ///
583     /// ```
584     /// use flagset::{FlagSet, flags};
585     ///
586     /// flags! {
587     ///     enum Flag: u64 {
588     ///         Foo = 0b001,
589     ///         Bar = 0b010,
590     ///         Baz = 0b100
591     ///     }
592     /// }
593     ///
594     /// let mut set0 = Flag::Foo | Flag::Bar;
595     /// let mut set1 = Flag::Bar | Flag::Baz;
596     ///
597     /// set0 |= set1;
598     /// assert_eq!(set0, FlagSet::full());
599     ///
600     /// set1 |= Flag::Baz;
601     /// assert_eq!(set1, Flag::Bar | Flag::Baz);
602     /// ```
603     #[inline]
bitor_assign(&mut self, rhs: R)604     fn bitor_assign(&mut self, rhs: R) {
605         self.0 |= rhs.into().0
606     }
607 }
608 
609 impl<F: Flags, R: Into<FlagSet<F>>> BitXor<R> for FlagSet<F> {
610     type Output = Self;
611 
612     /// Calculates the current set with the specified flags toggled.
613     ///
614     /// This is commonly known as toggling the presence
615     ///
616     /// ```
617     /// use flagset::{FlagSet, flags};
618     ///
619     /// flags! {
620     ///     enum Flag: u32 {
621     ///         Foo = 0b001,
622     ///         Bar = 0b010,
623     ///         Baz = 0b100
624     ///     }
625     /// }
626     ///
627     /// let set0 = Flag::Foo | Flag::Bar;
628     /// let set1 = Flag::Baz | Flag::Bar;
629     /// assert_eq!(set0 ^ set1, Flag::Foo | Flag::Baz);
630     /// assert_eq!(set0 ^ Flag::Foo, Flag::Bar);
631     /// ```
632     #[inline]
bitxor(self, rhs: R) -> Self633     fn bitxor(self, rhs: R) -> Self {
634         FlagSet(self.0 ^ rhs.into().0)
635     }
636 }
637 
638 impl<F: Flags, R: Into<FlagSet<F>>> BitXorAssign<R> for FlagSet<F> {
639     /// Assigns the current set with the specified flags toggled.
640     ///
641     /// ```
642     /// use flagset::{FlagSet, flags};
643     ///
644     /// flags! {
645     ///     enum Flag: u16 {
646     ///         Foo = 0b001,
647     ///         Bar = 0b010,
648     ///         Baz = 0b100
649     ///     }
650     /// }
651     ///
652     /// let mut set0 = Flag::Foo | Flag::Bar;
653     /// let mut set1 = Flag::Baz | Flag::Bar;
654     ///
655     /// set0 ^= set1;
656     /// assert_eq!(set0, Flag::Foo | Flag::Baz);
657     ///
658     /// set1 ^= Flag::Baz;
659     /// assert_eq!(set1, Flag::Bar);
660     /// ```
661     #[inline]
bitxor_assign(&mut self, rhs: R)662     fn bitxor_assign(&mut self, rhs: R) {
663         self.0 ^= rhs.into().0
664     }
665 }
666 
667 impl<F: Flags, R: Into<FlagSet<F>>> Sub<R> for FlagSet<F> {
668     type Output = Self;
669 
670     /// Calculates set difference (the current set without the specified flags).
671     ///
672     /// ```
673     /// use flagset::{FlagSet, flags};
674     ///
675     /// flags! {
676     ///     pub enum Flag: u8 {
677     ///         Foo = 1,
678     ///         Bar = 2,
679     ///         Baz = 4
680     ///     }
681     /// }
682     ///
683     /// let set0 = Flag::Foo | Flag::Bar;
684     /// let set1 = Flag::Baz | Flag::Bar;
685     /// assert_eq!(set0 - set1, Flag::Foo);
686     /// ```
687     #[inline]
sub(self, rhs: R) -> Self688     fn sub(self, rhs: R) -> Self {
689         self & !rhs.into()
690     }
691 }
692 
693 impl<F: Flags, R: Into<FlagSet<F>>> SubAssign<R> for FlagSet<F> {
694     /// Assigns set difference (the current set without the specified flags).
695     ///
696     /// ```
697     /// use flagset::{FlagSet, flags};
698     ///
699     /// flags! {
700     ///     pub enum Flag: u8 {
701     ///         Foo = 1,
702     ///         Bar = 2,
703     ///         Baz = 4
704     ///     }
705     /// }
706     ///
707     /// let mut set0 = Flag::Foo | Flag::Bar;
708     /// set0 -= Flag::Baz | Flag::Bar;
709     /// assert_eq!(set0, Flag::Foo);
710     /// ```
711     #[inline]
sub_assign(&mut self, rhs: R)712     fn sub_assign(&mut self, rhs: R) {
713         *self &= !rhs.into();
714     }
715 }
716 
717 impl<F: Flags, R: Into<FlagSet<F>>> Rem<R> for FlagSet<F> {
718     type Output = Self;
719 
720     /// Calculates the symmetric difference between two sets.
721     ///
722     /// The symmetric difference between two sets is the set of all flags
723     /// that appear in one set or the other, but not both.
724     ///
725     /// ```
726     /// use flagset::{FlagSet, flags};
727     ///
728     /// flags! {
729     ///     pub enum Flag: u8 {
730     ///         Foo = 1,
731     ///         Bar = 2,
732     ///         Baz = 4
733     ///     }
734     /// }
735     ///
736     /// let set0 = Flag::Foo | Flag::Bar;
737     /// let set1 = Flag::Baz | Flag::Bar;
738     /// assert_eq!(set0 % set1, Flag::Foo | Flag::Baz);
739     /// ```
740     #[inline]
rem(self, rhs: R) -> Self741     fn rem(self, rhs: R) -> Self {
742         let rhs = rhs.into();
743         (self - rhs) | (rhs - self)
744     }
745 }
746 
747 impl<F: Flags, R: Into<FlagSet<F>>> RemAssign<R> for FlagSet<F> {
748     /// Assigns the symmetric difference between two sets.
749     ///
750     /// The symmetric difference between two sets is the set of all flags
751     /// that appear in one set or the other, but not both.
752     ///
753     /// ```
754     /// use flagset::{FlagSet, flags};
755     ///
756     /// flags! {
757     ///     pub enum Flag: u8 {
758     ///         Foo = 1,
759     ///         Bar = 2,
760     ///         Baz = 4
761     ///     }
762     /// }
763     ///
764     /// let mut set0 = Flag::Foo | Flag::Bar;
765     /// let set1 = Flag::Baz | Flag::Bar;
766     /// set0 %= set1;
767     /// assert_eq!(set0, Flag::Foo | Flag::Baz);
768     /// ```
769     #[inline]
rem_assign(&mut self, rhs: R)770     fn rem_assign(&mut self, rhs: R) {
771         *self = *self % rhs
772     }
773 }
774 
775 impl<F: Flags> FlagSet<F> {
776     /// Creates a new set from bits; returning `Err(InvalidBits)` on invalid/unknown bits.
777     ///
778     /// ```
779     /// use flagset::{FlagSet, flags};
780     ///
781     /// flags! {
782     ///     pub enum Flag: u16 {
783     ///         Foo = 0b0001,
784     ///         Bar = 0b0010,
785     ///         Baz = 0b0100,
786     ///         Qux = 0b1010, // Implies Bar
787     ///     }
788     /// }
789     ///
790     /// assert_eq!(FlagSet::<Flag>::new(0b00101), Ok(Flag::Foo | Flag::Baz));
791     /// assert_eq!(FlagSet::<Flag>::new(0b01101), Err(flagset::InvalidBits)); // Invalid
792     /// assert_eq!(FlagSet::<Flag>::new(0b10101), Err(flagset::InvalidBits)); // Unknown
793     /// ```
794     #[inline]
new(bits: F::Type) -> core::result::Result<Self, InvalidBits>795     pub fn new(bits: F::Type) -> core::result::Result<Self, InvalidBits> {
796         if Self::new_truncated(bits).0 == bits {
797             return Ok(FlagSet(bits));
798         }
799 
800         Err(InvalidBits)
801     }
802 
803     /// Creates a new set from bits; truncating invalid/unknown bits.
804     ///
805     /// ```
806     /// use flagset::{FlagSet, flags};
807     ///
808     /// flags! {
809     ///     pub enum Flag: u16 {
810     ///         Foo = 0b0001,
811     ///         Bar = 0b0010,
812     ///         Baz = 0b0100,
813     ///         Qux = 0b1010, // Implies Bar
814     ///     }
815     /// }
816     ///
817     /// let set = FlagSet::new_truncated(0b11101);  // Has invalid and unknown.
818     /// assert_eq!(set, Flag::Foo | Flag::Baz);
819     /// assert_eq!(set.bits(), 0b00101);            // Has neither.
820     /// ```
821     #[inline]
new_truncated(bits: F::Type) -> Self822     pub fn new_truncated(bits: F::Type) -> Self {
823         let mut set = Self::default();
824 
825         for flag in FlagSet::<F>(bits) {
826             set |= flag;
827         }
828 
829         set
830     }
831 
832     /// Creates a new set from bits; use of invalid/unknown bits is undefined.
833     ///
834     /// ```
835     /// use flagset::{FlagSet, flags};
836     ///
837     /// flags! {
838     ///     pub enum Flag: u16 {
839     ///         Foo = 0b0001,
840     ///         Bar = 0b0010,
841     ///         Baz = 0b0100,
842     ///         Qux = 0b1010, // Implies Bar
843     ///     }
844     /// }
845     ///
846     /// // Unknown and invalid bits are retained. Behavior is undefined.
847     /// let set = unsafe { FlagSet::<Flag>::new_unchecked(0b11101) };
848     /// assert_eq!(set.bits(), 0b11101);
849     /// ```
850     ///
851     /// # Safety
852     ///
853     /// This constructor doesn't check that the bits are valid. If you pass
854     /// undefined flags, undefined behavior may result.
855     #[inline]
new_unchecked(bits: F::Type) -> Self856     pub unsafe fn new_unchecked(bits: F::Type) -> Self {
857         FlagSet(bits)
858     }
859 
860     /// Creates a new FlagSet containing all possible flags.
861     ///
862     /// ```
863     /// use flagset::{FlagSet, flags};
864     ///
865     /// flags! {
866     ///     pub enum Flag: u8 {
867     ///         Foo = 1,
868     ///         Bar = 2,
869     ///         Baz = 4
870     ///     }
871     /// }
872     ///
873     /// let set = FlagSet::full();
874     /// assert!(!set.is_empty());
875     /// assert!(set.is_full());
876     /// assert!(set.contains(Flag::Foo));
877     /// assert!(set.contains(Flag::Bar));
878     /// assert!(set.contains(Flag::Baz));
879     /// ```
880     #[inline]
full() -> Self881     pub fn full() -> Self {
882         let mut set = Self::default();
883         for f in F::LIST {
884             set |= *f
885         }
886         set
887     }
888 
889     /// Returns the raw bits of the set.
890     ///
891     /// ```
892     /// use flagset::{FlagSet, flags};
893     ///
894     /// flags! {
895     ///     pub enum Flag: u16 {
896     ///         Foo = 0b0001,
897     ///         Bar = 0b0010,
898     ///         Baz = 0b0100,
899     ///     }
900     /// }
901     ///
902     /// let set = Flag::Foo | Flag::Baz;
903     /// assert_eq!(set.bits(), 0b0101u16);
904     /// ```
905     #[inline]
bits(self) -> F::Type906     pub fn bits(self) -> F::Type {
907         self.0
908     }
909 
910     /// Returns true if the FlagSet contains no flags.
911     ///
912     /// ```
913     /// use flagset::{FlagSet, flags};
914     ///
915     /// flags! {
916     ///     pub enum Flag: u8 {
917     ///         Foo = 1,
918     ///         Bar = 2,
919     ///         Baz = 4
920     ///     }
921     /// }
922     ///
923     /// let mut set = Flag::Foo | Flag::Bar;
924     /// assert!(!set.is_empty());
925     ///
926     /// set &= Flag::Baz;
927     /// assert!(set.is_empty());
928     /// ```
929     #[inline]
is_empty(self) -> bool930     pub fn is_empty(self) -> bool {
931         self == Self::default()
932     }
933 
934     /// Returns true if the FlagSet contains all possible flags.
935     ///
936     /// ```
937     /// use flagset::{FlagSet, flags};
938     ///
939     /// flags! {
940     ///     pub enum Flag: u8 {
941     ///         Foo = 1,
942     ///         Bar = 2,
943     ///         Baz = 4
944     ///     }
945     /// }
946     ///
947     /// let mut set = Flag::Foo | Flag::Bar;
948     /// assert!(!set.is_full());
949     ///
950     /// set |= Flag::Baz;
951     /// assert!(set.is_full());
952     /// ```
953     #[inline]
is_full(self) -> bool954     pub fn is_full(self) -> bool {
955         self == Self::full()
956     }
957 
958     /// Returns true if the two `FlagSet`s do not share any flags.
959     ///
960     /// ```
961     /// use flagset::{FlagSet, flags};
962     ///
963     /// flags! {
964     ///     pub enum Flag: u8 {
965     ///         Foo = 1,
966     ///         Bar = 2,
967     ///         Baz = 4
968     ///     }
969     /// }
970     ///
971     /// let set = Flag::Foo | Flag::Bar;
972     /// assert!(!set.is_disjoint(Flag::Foo));
973     /// assert!(!set.is_disjoint(Flag::Foo | Flag::Baz));
974     /// assert!(set.is_disjoint(Flag::Baz));
975     /// ```
976     #[inline]
is_disjoint(self, rhs: impl Into<FlagSet<F>>) -> bool977     pub fn is_disjoint(self, rhs: impl Into<FlagSet<F>>) -> bool {
978         self & rhs == Self::default()
979     }
980 
981     /// Returns true if this FlagSet is a superset of the specified flags.
982     ///
983     /// ```
984     /// use flagset::{FlagSet, flags};
985     ///
986     /// flags! {
987     ///     pub enum Flag: u8 {
988     ///         Foo = 1,
989     ///         Bar = 2,
990     ///         Baz = 4
991     ///     }
992     /// }
993     ///
994     /// let set = Flag::Foo | Flag::Bar;
995     /// assert!(set.contains(Flag::Foo));
996     /// assert!(set.contains(Flag::Foo | Flag::Bar));
997     /// assert!(!set.contains(Flag::Foo | Flag::Bar | Flag::Baz));
998     /// ```
999     #[inline]
contains(self, rhs: impl Into<FlagSet<F>>) -> bool1000     pub fn contains(self, rhs: impl Into<FlagSet<F>>) -> bool {
1001         let rhs = rhs.into();
1002         self & rhs == rhs
1003     }
1004 
1005     /// Removes all flags from the FlagSet.
1006     ///
1007     /// ```
1008     /// use flagset::{FlagSet, flags};
1009     ///
1010     /// flags! {
1011     ///     pub enum Flag: u8 {
1012     ///         Foo = 1,
1013     ///         Bar = 2,
1014     ///         Baz = 4
1015     ///     }
1016     /// }
1017     ///
1018     /// let mut set = Flag::Foo | Flag::Bar;
1019     /// assert!(!set.is_empty());
1020     ///
1021     /// set.clear();
1022     /// assert!(set.is_empty());
1023     /// ```
1024     #[inline]
clear(&mut self)1025     pub fn clear(&mut self) {
1026         *self = Self::default();
1027     }
1028 
1029     /// Clears the current set and returns an iterator of all removed flags.
1030     ///
1031     /// ```
1032     /// use flagset::{FlagSet, flags};
1033     ///
1034     /// flags! {
1035     ///     pub enum Flag: u8 {
1036     ///         Foo = 1,
1037     ///         Bar = 2,
1038     ///         Baz = 4
1039     ///     }
1040     /// }
1041     ///
1042     /// let mut set = Flag::Foo | Flag::Bar;
1043     /// let mut iter = set.drain();
1044     /// assert!(set.is_empty());
1045     /// assert_eq!(iter.next(), Some(Flag::Foo));
1046     /// assert_eq!(iter.next(), Some(Flag::Bar));
1047     /// assert_eq!(iter.next(), None);
1048     /// ```
1049     #[inline]
drain(&mut self) -> Iter<F>1050     pub fn drain(&mut self) -> Iter<F> {
1051         let iter = self.into_iter();
1052         *self = Self::default();
1053         iter
1054     }
1055 
1056     /// Retain only the flags flags specified by the predicate.
1057     ///
1058     /// ```
1059     /// use flagset::{FlagSet, flags};
1060     ///
1061     /// flags! {
1062     ///     pub enum Flag: u8 {
1063     ///         Foo = 1,
1064     ///         Bar = 2,
1065     ///         Baz = 4
1066     ///     }
1067     /// }
1068     ///
1069     /// let mut set0 = Flag::Foo | Flag::Bar;
1070     /// set0.retain(|f| f != Flag::Foo);
1071     /// assert_eq!(set0, Flag::Bar);
1072     /// ```
1073     #[inline]
retain(&mut self, func: impl Fn(F) -> bool)1074     pub fn retain(&mut self, func: impl Fn(F) -> bool) {
1075         for f in self.into_iter() {
1076             if !func(f) {
1077                 *self -= f
1078             }
1079         }
1080     }
1081 }
1082 
1083 #[cfg(feature = "serde")]
1084 impl<F: Flags> serde::Serialize for FlagSet<F>
1085 where
1086     F::Type: serde::ser::Serialize,
1087 {
1088     #[inline]
serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> where S: serde::ser::Serializer,1089     fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
1090     where
1091         S: serde::ser::Serializer,
1092     {
1093         self.0.serialize(serializer)
1094     }
1095 }
1096 
1097 #[cfg(feature = "serde")]
1098 impl<'de, F: Flags> serde::Deserialize<'de> for FlagSet<F>
1099 where
1100     F::Type: serde::de::Deserialize<'de>,
1101 {
1102     #[inline]
deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error> where D: serde::de::Deserializer<'de>,1103     fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
1104     where
1105         D: serde::de::Deserializer<'de>,
1106     {
1107         Ok(FlagSet(F::Type::deserialize(deserializer)?))
1108     }
1109 }
1110 
1111 /// Define flag value using the `enum` syntax. See below for details.
1112 ///
1113 /// Each enumeration value **MUST** have a specified value.
1114 ///
1115 /// The width of the bitfield **MUST** also be specified by its integer type.
1116 ///
1117 /// It is important to note that the size of the flag enumeration itself is
1118 /// unrelated to the size of the corresponding `FlagSet` instance.
1119 ///
1120 /// It is also worth noting that this macro automatically implements a variety
1121 /// of standard traits including:
1122 ///   * Copy
1123 ///   * Clone
1124 ///   * Debug
1125 ///   * PartialEq
1126 ///   * Eq
1127 ///   * From<$enum> for $integer
1128 ///   * Not
1129 ///   * BitAnd
1130 ///   * BitOr
1131 ///   * BitXor
1132 ///   * Sub
1133 ///   * Rem
1134 ///
1135 /// ```
1136 /// use std::mem::{align_of, size_of};
1137 /// use flagset::{FlagSet, flags};
1138 ///
1139 /// flags! {
1140 ///     enum FlagEmpty: u32 {}
1141 ///
1142 ///     enum Flag8: u8 {
1143 ///         Foo = 0b001,
1144 ///         Bar = 0b010,
1145 ///         Baz = 0b100
1146 ///     }
1147 ///
1148 ///     pub enum Flag16: u16 {
1149 ///         Foo,
1150 ///         Bar,
1151 ///         #[deprecated]
1152 ///         Baz,
1153 ///     }
1154 ///
1155 ///     #[derive(PartialOrd, Ord)]
1156 ///     enum Flag32: u32 {
1157 ///         Foo = 0b001,
1158 ///         #[deprecated]
1159 ///         Bar = 0b010,
1160 ///         Baz = 0b100
1161 ///     }
1162 ///
1163 ///     #[repr(u64)]
1164 ///     enum Flag64: u64 {
1165 ///         Foo = 0b001,
1166 ///         Bar = 0b010,
1167 ///         Baz = 0b100
1168 ///     }
1169 ///
1170 ///     #[repr(u32)]
1171 ///     enum Flag128: u128 {
1172 ///         Foo = 0b001,
1173 ///         Bar = 0b010,
1174 ///         Baz = 0b100
1175 ///     }
1176 /// }
1177 ///
1178 /// assert_eq!(size_of::<Flag8>(), 1);
1179 /// assert_eq!(size_of::<Flag16>(), 1);
1180 /// assert_eq!(size_of::<Flag32>(), 1);
1181 /// assert_eq!(size_of::<Flag64>(), 8);
1182 /// assert_eq!(size_of::<Flag128>(), 4);
1183 ///
1184 /// assert_eq!(align_of::<Flag8>(), 1);
1185 /// assert_eq!(align_of::<Flag16>(), 1);
1186 /// assert_eq!(align_of::<Flag32>(), 1);
1187 /// assert_eq!(align_of::<Flag64>(), align_of::<u64>());
1188 /// assert_eq!(align_of::<Flag128>(), align_of::<u32>());
1189 ///
1190 /// assert_eq!(size_of::<FlagSet<Flag8>>(), size_of::<u8>());
1191 /// assert_eq!(size_of::<FlagSet<Flag16>>(), size_of::<u16>());
1192 /// assert_eq!(size_of::<FlagSet<Flag32>>(), size_of::<u32>());
1193 /// assert_eq!(size_of::<FlagSet<Flag64>>(), size_of::<u64>());
1194 /// assert_eq!(size_of::<FlagSet<Flag128>>(), size_of::<u128>());
1195 ///
1196 /// assert_eq!(align_of::<FlagSet<Flag8>>(), align_of::<u8>());
1197 /// assert_eq!(align_of::<FlagSet<Flag16>>(), align_of::<u16>());
1198 /// assert_eq!(align_of::<FlagSet<Flag32>>(), align_of::<u32>());
1199 /// assert_eq!(align_of::<FlagSet<Flag64>>(), align_of::<u64>());
1200 /// assert_eq!(align_of::<FlagSet<Flag128>>(), align_of::<u128>());
1201 /// ```
1202 #[macro_export]
1203 macro_rules! flags {
1204     () => {};
1205 
1206     // Entry point for enumerations without values.
1207     ($(#[$m:meta])* $p:vis enum $n:ident: $t:ty { $($(#[$a:meta])* $k:ident),+ $(,)* } $($next:tt)*) => {
1208         $crate::flags! { $(#[$m])* $p enum $n: $t { $($(#[$a])* $k = (1 << $n::$k as $t)),+ } $($next)* }
1209     };
1210 
1211     // Entrypoint for enumerations with values.
1212     ($(#[$m:meta])* $p:vis enum $n:ident: $t:ty { $($(#[$a:meta])*$k:ident = $v:expr),* $(,)* } $($next:tt)*) => {
1213         $(#[$m])*
1214         #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1215         $p enum $n { $($(#[$a])* $k),* }
1216 
1217         impl $crate::Flags for $n {
1218             type Type = $t;
1219 
1220             const LIST: &'static [Self] = &[$($n::$k),*];
1221         }
1222 
1223         impl core::convert::From<$n> for $crate::FlagSet<$n> {
1224             #[inline]
1225             fn from(value: $n) -> Self {
1226                 unsafe {
1227                     match value {
1228                         $($n::$k => Self::new_unchecked($v)),*
1229                     }
1230                 }
1231             }
1232         }
1233 
1234         impl core::ops::Not for $n {
1235             type Output = $crate::FlagSet<$n>;
1236 
1237             #[inline]
1238             fn not(self) -> Self::Output {
1239                 !$crate::FlagSet::from(self)
1240             }
1241         }
1242 
1243         impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::BitAnd<R> for $n {
1244             type Output = $crate::FlagSet<$n>;
1245 
1246             #[inline]
1247             fn bitand(self, rhs: R) -> Self::Output {
1248                 $crate::FlagSet::from(self) & rhs
1249             }
1250         }
1251 
1252         impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::BitOr<R> for $n {
1253             type Output = $crate::FlagSet<$n>;
1254 
1255             #[inline]
1256             fn bitor(self, rhs: R) -> Self::Output {
1257                 $crate::FlagSet::from(self) | rhs
1258             }
1259         }
1260 
1261         impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::BitXor<R> for $n {
1262             type Output = $crate::FlagSet<$n>;
1263 
1264             #[inline]
1265             fn bitxor(self, rhs: R) -> Self::Output {
1266                 $crate::FlagSet::from(self) ^ rhs
1267             }
1268         }
1269 
1270         impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::Sub<R> for $n {
1271             type Output = $crate::FlagSet<$n>;
1272 
1273             #[inline]
1274             fn sub(self, rhs: R) -> Self::Output {
1275                 $crate::FlagSet::from(self) - rhs
1276             }
1277         }
1278 
1279         impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::Rem<R> for $n {
1280             type Output = $crate::FlagSet<$n>;
1281 
1282             #[inline]
1283             fn rem(self, rhs: R) -> Self::Output {
1284                 $crate::FlagSet::from(self) % rhs
1285             }
1286         }
1287 
1288         $crate::flags! { $($next)* }
1289     };
1290 }
1291