• 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 #![cfg_attr(not(feature = "std"), no_std)]
249 #![cfg_attr(docsrs, feature(doc_auto_cfg))]
250 
251 use core::fmt::{Debug, Formatter, Result};
252 use core::ops::*;
253 
254 /// Error type returned when creating a new flagset from bits is invalid or undefined.
255 /// ```
256 /// use flagset::{FlagSet, flags};
257 ///
258 /// flags! {
259 ///     pub enum Flag: u16 {
260 ///         Foo = 0b0001,
261 ///         Bar = 0b0010,
262 ///         Baz = 0b0100,
263 ///         Qux = 0b1010, // Implies Bar
264 ///     }
265 /// }
266 ///
267 /// assert_eq!(FlagSet::<Flag>::new(0b01101), Err(flagset::InvalidBits)); // Invalid
268 /// assert_eq!(FlagSet::<Flag>::new(0b10101), Err(flagset::InvalidBits)); // Unknown
269 /// ```
270 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
271 pub struct InvalidBits;
272 
273 impl core::fmt::Display for InvalidBits {
274     #[inline]
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result275     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
276         write!(f, "invalid bits")
277     }
278 }
279 
280 #[cfg(feature = "std")]
281 impl std::error::Error for InvalidBits {}
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 #[repr(C)]
324 #[derive(Copy, Clone, Eq, Hash)]
325 pub struct FlagSet<F: Flags>(F::Type);
326 
327 #[doc(hidden)]
328 #[derive(Copy, Clone)]
329 pub struct Iter<F: Flags>(FlagSet<F>, usize);
330 
331 impl<F: Flags> Iterator for Iter<F> {
332     type Item = F;
333 
334     #[inline]
next(&mut self) -> Option<Self::Item>335     fn next(&mut self) -> Option<Self::Item> {
336         while self.1 < F::LIST.len() {
337             let next = F::LIST[self.1];
338             self.1 += 1;
339 
340             if self.0.contains(next) {
341                 return Some(next);
342             }
343         }
344 
345         None
346     }
347 }
348 
349 impl<F: Flags> IntoIterator for FlagSet<F> {
350     type Item = F;
351     type IntoIter = Iter<F>;
352 
353     /// Iterate over the flags in the set.
354     ///
355     /// **NOTE**: The order in which the flags are iterated is undefined.
356     ///
357     /// ```
358     /// use flagset::{FlagSet, flags};
359     ///
360     /// flags! {
361     ///     enum Flag: u8 {
362     ///         Foo = 0b001,
363     ///         Bar = 0b010,
364     ///         Baz = 0b100
365     ///     }
366     /// }
367     ///
368     /// let set = Flag::Foo | Flag::Bar;
369     /// let mut iter = set.into_iter();
370     /// assert_eq!(iter.next(), Some(Flag::Foo));
371     /// assert_eq!(iter.next(), Some(Flag::Bar));
372     /// assert_eq!(iter.next(), None);
373     /// ```
374     #[inline]
into_iter(self) -> Self::IntoIter375     fn into_iter(self) -> Self::IntoIter {
376         Iter(self, 0)
377     }
378 }
379 
380 impl<F: Flags> Debug for FlagSet<F> {
381     #[inline]
fmt(&self, f: &mut Formatter) -> Result382     fn fmt(&self, f: &mut Formatter) -> Result {
383         write!(f, "FlagSet(")?;
384         for (i, flag) in self.into_iter().enumerate() {
385             write!(f, "{}{:?}", if i > 0 { " | " } else { "" }, flag)?;
386         }
387         write!(f, ")")
388     }
389 }
390 
391 impl<F: Flags, R: Copy + Into<FlagSet<F>>> PartialEq<R> for FlagSet<F> {
392     #[inline]
eq(&self, rhs: &R) -> bool393     fn eq(&self, rhs: &R) -> bool {
394         self.0 == (*rhs).into().0
395     }
396 }
397 
398 impl<F: Flags> AsRef<F::Type> for FlagSet<F> {
399     #[inline]
as_ref(&self) -> &F::Type400     fn as_ref(&self) -> &F::Type {
401         &self.0
402     }
403 }
404 
405 impl<F: Flags> From<Option<FlagSet<F>>> for FlagSet<F> {
406     /// Converts from `Option<FlagSet<F>>` to `FlagSet<F>`.
407     ///
408     /// Most notably, this allows for the use of `None` in many places to
409     /// substitute for manually creating an empty `FlagSet<F>`. See below.
410     ///
411     /// ```
412     /// use flagset::{FlagSet, flags};
413     ///
414     /// flags! {
415     ///     enum Flag: u8 {
416     ///         Foo = 0b001,
417     ///         Bar = 0b010,
418     ///         Baz = 0b100
419     ///     }
420     /// }
421     ///
422     /// fn convert(v: impl Into<FlagSet<Flag>>) -> u8 {
423     ///     v.into().bits()
424     /// }
425     ///
426     /// assert_eq!(convert(Flag::Foo | Flag::Bar), 0b011);
427     /// assert_eq!(convert(Flag::Foo), 0b001);
428     /// assert_eq!(convert(None), 0b000);
429     /// ```
430     #[inline]
from(value: Option<FlagSet<F>>) -> FlagSet<F>431     fn from(value: Option<FlagSet<F>>) -> FlagSet<F> {
432         value.unwrap_or_default()
433     }
434 }
435 
436 impl<F: Flags> Default for FlagSet<F> {
437     /// Creates a new, empty FlagSet.
438     ///
439     /// ```
440     /// use flagset::{FlagSet, flags};
441     ///
442     /// flags! {
443     ///     enum Flag: u8 {
444     ///         Foo = 0b001,
445     ///         Bar = 0b010,
446     ///         Baz = 0b100
447     ///     }
448     /// }
449     ///
450     /// let set = FlagSet::<Flag>::default();
451     /// assert!(set.is_empty());
452     /// assert!(!set.is_full());
453     /// assert!(!set.contains(Flag::Foo));
454     /// assert!(!set.contains(Flag::Bar));
455     /// assert!(!set.contains(Flag::Baz));
456     /// ```
457     #[inline]
default() -> Self458     fn default() -> Self {
459         FlagSet(F::Type::default())
460     }
461 }
462 
463 impl<F: Flags> Not for FlagSet<F> {
464     type Output = Self;
465 
466     /// Calculates the complement of the current set.
467     ///
468     /// In common parlance, this returns the set of all possible flags that are
469     /// not in the current set.
470     ///
471     /// ```
472     /// use flagset::{FlagSet, flags};
473     ///
474     /// flags! {
475     ///     #[derive(PartialOrd, Ord)]
476     ///     enum Flag: u8 {
477     ///         Foo = 1 << 0,
478     ///         Bar = 1 << 1,
479     ///         Baz = 1 << 2
480     ///     }
481     /// }
482     ///
483     /// let set = !FlagSet::from(Flag::Foo);
484     /// assert!(!set.is_empty());
485     /// assert!(!set.is_full());
486     /// assert!(!set.contains(Flag::Foo));
487     /// assert!(set.contains(Flag::Bar));
488     /// assert!(set.contains(Flag::Baz));
489     /// ```
490     #[inline]
not(self) -> Self491     fn not(self) -> Self {
492         FlagSet(!self.0)
493     }
494 }
495 
496 impl<F: Flags, R: Into<FlagSet<F>>> BitAnd<R> for FlagSet<F> {
497     type Output = Self;
498 
499     /// Calculates the intersection of the current set and the specified flags.
500     ///
501     /// ```
502     /// use flagset::{FlagSet, flags};
503     ///
504     /// flags! {
505     ///     #[derive(PartialOrd, Ord)]
506     ///     pub enum Flag: u8 {
507     ///         Foo = 0b001,
508     ///         Bar = 0b010,
509     ///         Baz = 0b100
510     ///     }
511     /// }
512     ///
513     /// let set0 = Flag::Foo | Flag::Bar;
514     /// let set1 = Flag::Baz | Flag::Bar;
515     /// assert_eq!(set0 & set1, Flag::Bar);
516     /// assert_eq!(set0 & Flag::Foo, Flag::Foo);
517     /// assert_eq!(set1 & Flag::Baz, Flag::Baz);
518     /// ```
519     #[inline]
bitand(self, rhs: R) -> Self520     fn bitand(self, rhs: R) -> Self {
521         FlagSet(self.0 & rhs.into().0)
522     }
523 }
524 
525 impl<F: Flags, R: Into<FlagSet<F>>> BitAndAssign<R> for FlagSet<F> {
526     /// Assigns the intersection of the current set and the specified flags.
527     ///
528     /// ```
529     /// use flagset::{FlagSet, flags};
530     ///
531     /// flags! {
532     ///     enum Flag: u64 {
533     ///         Foo = 0b001,
534     ///         Bar = 0b010,
535     ///         Baz = 0b100
536     ///     }
537     /// }
538     ///
539     /// let mut set0 = Flag::Foo | Flag::Bar;
540     /// let mut set1 = Flag::Baz | Flag::Bar;
541     ///
542     /// set0 &= set1;
543     /// assert_eq!(set0, Flag::Bar);
544     ///
545     /// set1 &= Flag::Baz;
546     /// assert_eq!(set0, Flag::Bar);
547     /// ```
548     #[inline]
bitand_assign(&mut self, rhs: R)549     fn bitand_assign(&mut self, rhs: R) {
550         self.0 &= rhs.into().0
551     }
552 }
553 
554 impl<F: Flags, R: Into<FlagSet<F>>> BitOr<R> for FlagSet<F> {
555     type Output = Self;
556 
557     /// Calculates the union of the current set with the specified flags.
558     ///
559     /// ```
560     /// use flagset::{FlagSet, flags};
561     ///
562     /// flags! {
563     ///     #[derive(PartialOrd, Ord)]
564     ///     pub enum Flag: u8 {
565     ///         Foo = 0b001,
566     ///         Bar = 0b010,
567     ///         Baz = 0b100
568     ///     }
569     /// }
570     ///
571     /// let set0 = Flag::Foo | Flag::Bar;
572     /// let set1 = Flag::Baz | Flag::Bar;
573     /// assert_eq!(set0 | set1, FlagSet::full());
574     /// ```
575     #[inline]
bitor(self, rhs: R) -> Self576     fn bitor(self, rhs: R) -> Self {
577         FlagSet(self.0 | rhs.into().0)
578     }
579 }
580 
581 impl<F: Flags, R: Into<FlagSet<F>>> BitOrAssign<R> for FlagSet<F> {
582     /// Assigns the union of the current set with the specified flags.
583     ///
584     /// ```
585     /// use flagset::{FlagSet, flags};
586     ///
587     /// flags! {
588     ///     enum Flag: u64 {
589     ///         Foo = 0b001,
590     ///         Bar = 0b010,
591     ///         Baz = 0b100
592     ///     }
593     /// }
594     ///
595     /// let mut set0 = Flag::Foo | Flag::Bar;
596     /// let mut set1 = Flag::Bar | Flag::Baz;
597     ///
598     /// set0 |= set1;
599     /// assert_eq!(set0, FlagSet::full());
600     ///
601     /// set1 |= Flag::Baz;
602     /// assert_eq!(set1, Flag::Bar | Flag::Baz);
603     /// ```
604     #[inline]
bitor_assign(&mut self, rhs: R)605     fn bitor_assign(&mut self, rhs: R) {
606         self.0 |= rhs.into().0
607     }
608 }
609 
610 impl<F: Flags, R: Into<FlagSet<F>>> BitXor<R> for FlagSet<F> {
611     type Output = Self;
612 
613     /// Calculates the current set with the specified flags toggled.
614     ///
615     /// This is commonly known as toggling the presence
616     ///
617     /// ```
618     /// use flagset::{FlagSet, flags};
619     ///
620     /// flags! {
621     ///     enum Flag: u32 {
622     ///         Foo = 0b001,
623     ///         Bar = 0b010,
624     ///         Baz = 0b100
625     ///     }
626     /// }
627     ///
628     /// let set0 = Flag::Foo | Flag::Bar;
629     /// let set1 = Flag::Baz | Flag::Bar;
630     /// assert_eq!(set0 ^ set1, Flag::Foo | Flag::Baz);
631     /// assert_eq!(set0 ^ Flag::Foo, Flag::Bar);
632     /// ```
633     #[inline]
bitxor(self, rhs: R) -> Self634     fn bitxor(self, rhs: R) -> Self {
635         FlagSet(self.0 ^ rhs.into().0)
636     }
637 }
638 
639 impl<F: Flags, R: Into<FlagSet<F>>> BitXorAssign<R> for FlagSet<F> {
640     /// Assigns the current set with the specified flags toggled.
641     ///
642     /// ```
643     /// use flagset::{FlagSet, flags};
644     ///
645     /// flags! {
646     ///     enum Flag: u16 {
647     ///         Foo = 0b001,
648     ///         Bar = 0b010,
649     ///         Baz = 0b100
650     ///     }
651     /// }
652     ///
653     /// let mut set0 = Flag::Foo | Flag::Bar;
654     /// let mut set1 = Flag::Baz | Flag::Bar;
655     ///
656     /// set0 ^= set1;
657     /// assert_eq!(set0, Flag::Foo | Flag::Baz);
658     ///
659     /// set1 ^= Flag::Baz;
660     /// assert_eq!(set1, Flag::Bar);
661     /// ```
662     #[inline]
bitxor_assign(&mut self, rhs: R)663     fn bitxor_assign(&mut self, rhs: R) {
664         self.0 ^= rhs.into().0
665     }
666 }
667 
668 impl<F: Flags, R: Into<FlagSet<F>>> Sub<R> for FlagSet<F> {
669     type Output = Self;
670 
671     /// Calculates set difference (the current set without the specified flags).
672     ///
673     /// ```
674     /// use flagset::{FlagSet, flags};
675     ///
676     /// flags! {
677     ///     pub enum Flag: u8 {
678     ///         Foo = 1,
679     ///         Bar = 2,
680     ///         Baz = 4
681     ///     }
682     /// }
683     ///
684     /// let set0 = Flag::Foo | Flag::Bar;
685     /// let set1 = Flag::Baz | Flag::Bar;
686     /// assert_eq!(set0 - set1, Flag::Foo);
687     /// ```
688     #[inline]
sub(self, rhs: R) -> Self689     fn sub(self, rhs: R) -> Self {
690         self & !rhs.into()
691     }
692 }
693 
694 impl<F: Flags, R: Into<FlagSet<F>>> SubAssign<R> for FlagSet<F> {
695     /// Assigns set difference (the current set without the specified flags).
696     ///
697     /// ```
698     /// use flagset::{FlagSet, flags};
699     ///
700     /// flags! {
701     ///     pub enum Flag: u8 {
702     ///         Foo = 1,
703     ///         Bar = 2,
704     ///         Baz = 4
705     ///     }
706     /// }
707     ///
708     /// let mut set0 = Flag::Foo | Flag::Bar;
709     /// set0 -= Flag::Baz | Flag::Bar;
710     /// assert_eq!(set0, Flag::Foo);
711     /// ```
712     #[inline]
sub_assign(&mut self, rhs: R)713     fn sub_assign(&mut self, rhs: R) {
714         *self &= !rhs.into();
715     }
716 }
717 
718 impl<F: Flags, R: Into<FlagSet<F>>> Rem<R> for FlagSet<F> {
719     type Output = Self;
720 
721     /// Calculates the symmetric difference between two sets.
722     ///
723     /// The symmetric difference between two sets is the set of all flags
724     /// that appear in one set or the other, but not both.
725     ///
726     /// ```
727     /// use flagset::{FlagSet, flags};
728     ///
729     /// flags! {
730     ///     pub enum Flag: u8 {
731     ///         Foo = 1,
732     ///         Bar = 2,
733     ///         Baz = 4
734     ///     }
735     /// }
736     ///
737     /// let set0 = Flag::Foo | Flag::Bar;
738     /// let set1 = Flag::Baz | Flag::Bar;
739     /// assert_eq!(set0 % set1, Flag::Foo | Flag::Baz);
740     /// ```
741     #[inline]
rem(self, rhs: R) -> Self742     fn rem(self, rhs: R) -> Self {
743         let rhs = rhs.into();
744         (self - rhs) | (rhs - self)
745     }
746 }
747 
748 impl<F: Flags, R: Into<FlagSet<F>>> RemAssign<R> for FlagSet<F> {
749     /// Assigns the symmetric difference between two sets.
750     ///
751     /// The symmetric difference between two sets is the set of all flags
752     /// that appear in one set or the other, but not both.
753     ///
754     /// ```
755     /// use flagset::{FlagSet, flags};
756     ///
757     /// flags! {
758     ///     pub enum Flag: u8 {
759     ///         Foo = 1,
760     ///         Bar = 2,
761     ///         Baz = 4
762     ///     }
763     /// }
764     ///
765     /// let mut set0 = Flag::Foo | Flag::Bar;
766     /// let set1 = Flag::Baz | Flag::Bar;
767     /// set0 %= set1;
768     /// assert_eq!(set0, Flag::Foo | Flag::Baz);
769     /// ```
770     #[inline]
rem_assign(&mut self, rhs: R)771     fn rem_assign(&mut self, rhs: R) {
772         *self = *self % rhs
773     }
774 }
775 
776 impl<F: Flags, R: Into<FlagSet<F>>> Extend<R> for FlagSet<F> {
777     /// Add values by iterating over some collection.
778     ///
779     /// ```
780     /// use flagset::{FlagSet, flags};
781     ///
782     /// flags! {
783     ///     pub enum Flag: u8 {
784     ///         Foo = 1,
785     ///         Bar = 2,
786     ///         Baz = 4
787     ///     }
788     /// }
789     ///
790     /// let flag_vec = vec![Flag::Bar, Flag::Baz];
791     /// let mut some_extended_flags = FlagSet::from(Flag::Foo);
792     /// some_extended_flags.extend(flag_vec);
793     /// assert_eq!(some_extended_flags, Flag::Foo | Flag::Bar | Flag::Baz);
794     /// ```
extend<T>(&mut self, iter: T) where T: IntoIterator<Item = R>,795     fn extend<T>(&mut self, iter: T)
796     where
797         T: IntoIterator<Item = R>,
798     {
799         for item in iter {
800             *self |= item;
801         }
802     }
803 }
804 
805 impl<F: Flags> FlagSet<F> {
806     /// Creates a new set from bits; returning `Err(InvalidBits)` on invalid/unknown bits.
807     ///
808     /// ```
809     /// use flagset::{FlagSet, flags};
810     ///
811     /// flags! {
812     ///     pub enum Flag: u16 {
813     ///         Foo = 0b0001,
814     ///         Bar = 0b0010,
815     ///         Baz = 0b0100,
816     ///         Qux = 0b1010, // Implies Bar
817     ///     }
818     /// }
819     ///
820     /// assert_eq!(FlagSet::<Flag>::new(0b00101), Ok(Flag::Foo | Flag::Baz));
821     /// assert_eq!(FlagSet::<Flag>::new(0b01101), Err(flagset::InvalidBits)); // Invalid
822     /// assert_eq!(FlagSet::<Flag>::new(0b10101), Err(flagset::InvalidBits)); // Unknown
823     /// ```
824     #[inline]
new(bits: F::Type) -> core::result::Result<Self, InvalidBits>825     pub fn new(bits: F::Type) -> core::result::Result<Self, InvalidBits> {
826         if Self::new_truncated(bits).0 == bits {
827             return Ok(FlagSet(bits));
828         }
829 
830         Err(InvalidBits)
831     }
832 
833     /// Creates a new set from bits; truncating invalid/unknown bits.
834     ///
835     /// ```
836     /// use flagset::{FlagSet, flags};
837     ///
838     /// flags! {
839     ///     pub enum Flag: u16 {
840     ///         Foo = 0b0001,
841     ///         Bar = 0b0010,
842     ///         Baz = 0b0100,
843     ///         Qux = 0b1010, // Implies Bar
844     ///     }
845     /// }
846     ///
847     /// let set = FlagSet::new_truncated(0b11101);  // Has invalid and unknown.
848     /// assert_eq!(set, Flag::Foo | Flag::Baz);
849     /// assert_eq!(set.bits(), 0b00101);            // Has neither.
850     /// ```
851     #[inline]
new_truncated(bits: F::Type) -> Self852     pub fn new_truncated(bits: F::Type) -> Self {
853         let mut set = Self::default();
854 
855         for flag in FlagSet::<F>(bits) {
856             set |= flag;
857         }
858 
859         set
860     }
861 
862     /// Creates a new set from bits; use of invalid/unknown bits is undefined.
863     ///
864     /// ```
865     /// use flagset::{FlagSet, flags};
866     ///
867     /// flags! {
868     ///     pub enum Flag: u16 {
869     ///         Foo = 0b0001,
870     ///         Bar = 0b0010,
871     ///         Baz = 0b0100,
872     ///         Qux = 0b1010, // Implies Bar
873     ///     }
874     /// }
875     ///
876     /// // Unknown and invalid bits are retained. Behavior is undefined.
877     /// const set: FlagSet<Flag> = unsafe { FlagSet::<Flag>::new_unchecked(0b11101) };
878     /// assert_eq!(set.bits(), 0b11101);
879     /// ```
880     ///
881     /// # Safety
882     ///
883     /// This constructor doesn't check that the bits are valid. If you pass
884     /// undefined flags, undefined behavior may result.
885     #[inline]
new_unchecked(bits: F::Type) -> Self886     pub const unsafe fn new_unchecked(bits: F::Type) -> Self {
887         FlagSet(bits)
888     }
889 
890     /// Creates a new FlagSet containing all possible flags.
891     ///
892     /// ```
893     /// use flagset::{FlagSet, flags};
894     ///
895     /// flags! {
896     ///     pub enum Flag: u8 {
897     ///         Foo = 1,
898     ///         Bar = 2,
899     ///         Baz = 4
900     ///     }
901     /// }
902     ///
903     /// let set = FlagSet::full();
904     /// assert!(!set.is_empty());
905     /// assert!(set.is_full());
906     /// assert!(set.contains(Flag::Foo));
907     /// assert!(set.contains(Flag::Bar));
908     /// assert!(set.contains(Flag::Baz));
909     /// ```
910     #[inline]
full() -> Self911     pub fn full() -> Self {
912         let mut set = Self::default();
913         for f in F::LIST {
914             set |= *f
915         }
916         set
917     }
918 
919     /// Returns the raw bits of the set.
920     ///
921     /// ```
922     /// use flagset::{FlagSet, flags};
923     ///
924     /// flags! {
925     ///     pub enum Flag: u16 {
926     ///         Foo = 0b0001,
927     ///         Bar = 0b0010,
928     ///         Baz = 0b0100,
929     ///     }
930     /// }
931     ///
932     /// let set = Flag::Foo | Flag::Baz;
933     /// assert_eq!(set.bits(), 0b0101u16);
934     /// ```
935     #[inline]
bits(self) -> F::Type936     pub fn bits(self) -> F::Type {
937         self.0
938     }
939 
940     /// Returns true if the FlagSet contains no flags.
941     ///
942     /// ```
943     /// use flagset::{FlagSet, flags};
944     ///
945     /// flags! {
946     ///     pub enum Flag: u8 {
947     ///         Foo = 1,
948     ///         Bar = 2,
949     ///         Baz = 4
950     ///     }
951     /// }
952     ///
953     /// let mut set = Flag::Foo | Flag::Bar;
954     /// assert!(!set.is_empty());
955     ///
956     /// set &= Flag::Baz;
957     /// assert!(set.is_empty());
958     /// ```
959     #[inline]
is_empty(self) -> bool960     pub fn is_empty(self) -> bool {
961         self == Self::default()
962     }
963 
964     /// Returns true if the FlagSet contains all possible flags.
965     ///
966     /// ```
967     /// use flagset::{FlagSet, flags};
968     ///
969     /// flags! {
970     ///     pub enum Flag: u8 {
971     ///         Foo = 1,
972     ///         Bar = 2,
973     ///         Baz = 4
974     ///     }
975     /// }
976     ///
977     /// let mut set = Flag::Foo | Flag::Bar;
978     /// assert!(!set.is_full());
979     ///
980     /// set |= Flag::Baz;
981     /// assert!(set.is_full());
982     /// ```
983     #[inline]
is_full(self) -> bool984     pub fn is_full(self) -> bool {
985         self == Self::full()
986     }
987 
988     /// Returns true if the two `FlagSet`s do not share any flags.
989     ///
990     /// ```
991     /// use flagset::{FlagSet, flags};
992     ///
993     /// flags! {
994     ///     pub enum Flag: u8 {
995     ///         Foo = 1,
996     ///         Bar = 2,
997     ///         Baz = 4
998     ///     }
999     /// }
1000     ///
1001     /// let set = Flag::Foo | Flag::Bar;
1002     /// assert!(!set.is_disjoint(Flag::Foo));
1003     /// assert!(!set.is_disjoint(Flag::Foo | Flag::Baz));
1004     /// assert!(set.is_disjoint(Flag::Baz));
1005     /// ```
1006     #[inline]
is_disjoint(self, rhs: impl Into<FlagSet<F>>) -> bool1007     pub fn is_disjoint(self, rhs: impl Into<FlagSet<F>>) -> bool {
1008         self & rhs == Self::default()
1009     }
1010 
1011     /// Returns true if this FlagSet is a superset of the specified flags.
1012     ///
1013     /// ```
1014     /// use flagset::{FlagSet, flags};
1015     ///
1016     /// flags! {
1017     ///     pub enum Flag: u8 {
1018     ///         Foo = 1,
1019     ///         Bar = 2,
1020     ///         Baz = 4
1021     ///     }
1022     /// }
1023     ///
1024     /// let set = Flag::Foo | Flag::Bar;
1025     /// assert!(set.contains(Flag::Foo));
1026     /// assert!(set.contains(Flag::Foo | Flag::Bar));
1027     /// assert!(!set.contains(Flag::Foo | Flag::Bar | Flag::Baz));
1028     /// ```
1029     #[inline]
contains(self, rhs: impl Into<FlagSet<F>>) -> bool1030     pub fn contains(self, rhs: impl Into<FlagSet<F>>) -> bool {
1031         let rhs = rhs.into();
1032         self & rhs == rhs
1033     }
1034 
1035     /// Removes all flags from the FlagSet.
1036     ///
1037     /// ```
1038     /// use flagset::{FlagSet, flags};
1039     ///
1040     /// flags! {
1041     ///     pub enum Flag: u8 {
1042     ///         Foo = 1,
1043     ///         Bar = 2,
1044     ///         Baz = 4
1045     ///     }
1046     /// }
1047     ///
1048     /// let mut set = Flag::Foo | Flag::Bar;
1049     /// assert!(!set.is_empty());
1050     ///
1051     /// set.clear();
1052     /// assert!(set.is_empty());
1053     /// ```
1054     #[inline]
clear(&mut self)1055     pub fn clear(&mut self) {
1056         *self = Self::default();
1057     }
1058 
1059     /// Clears the current set and returns an iterator of all removed flags.
1060     ///
1061     /// ```
1062     /// use flagset::{FlagSet, flags};
1063     ///
1064     /// flags! {
1065     ///     pub enum Flag: u8 {
1066     ///         Foo = 1,
1067     ///         Bar = 2,
1068     ///         Baz = 4
1069     ///     }
1070     /// }
1071     ///
1072     /// let mut set = Flag::Foo | Flag::Bar;
1073     /// let mut iter = set.drain();
1074     /// assert!(set.is_empty());
1075     /// assert_eq!(iter.next(), Some(Flag::Foo));
1076     /// assert_eq!(iter.next(), Some(Flag::Bar));
1077     /// assert_eq!(iter.next(), None);
1078     /// ```
1079     #[inline]
drain(&mut self) -> Iter<F>1080     pub fn drain(&mut self) -> Iter<F> {
1081         let iter = self.into_iter();
1082         *self = Self::default();
1083         iter
1084     }
1085 
1086     /// Retain only the flags flags specified by the predicate.
1087     ///
1088     /// ```
1089     /// use flagset::{FlagSet, flags};
1090     ///
1091     /// flags! {
1092     ///     pub enum Flag: u8 {
1093     ///         Foo = 1,
1094     ///         Bar = 2,
1095     ///         Baz = 4
1096     ///     }
1097     /// }
1098     ///
1099     /// let mut set0 = Flag::Foo | Flag::Bar;
1100     /// set0.retain(|f| f != Flag::Foo);
1101     /// assert_eq!(set0, Flag::Bar);
1102     /// ```
1103     #[inline]
retain(&mut self, func: impl Fn(F) -> bool)1104     pub fn retain(&mut self, func: impl Fn(F) -> bool) {
1105         for f in self.into_iter() {
1106             if !func(f) {
1107                 *self -= f
1108             }
1109         }
1110     }
1111 }
1112 
1113 #[cfg(feature = "serde")]
1114 impl<F: Flags> serde::Serialize for FlagSet<F>
1115 where
1116     F::Type: serde::ser::Serialize,
1117 {
1118     #[inline]
serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> where S: serde::ser::Serializer,1119     fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
1120     where
1121         S: serde::ser::Serializer,
1122     {
1123         self.0.serialize(serializer)
1124     }
1125 }
1126 
1127 #[cfg(feature = "serde")]
1128 impl<'de, F: Flags> serde::Deserialize<'de> for FlagSet<F>
1129 where
1130     F::Type: serde::de::Deserialize<'de>,
1131 {
1132     #[inline]
deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error> where D: serde::de::Deserializer<'de>,1133     fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
1134     where
1135         D: serde::de::Deserializer<'de>,
1136     {
1137         Ok(FlagSet(F::Type::deserialize(deserializer)?))
1138     }
1139 }
1140 
1141 /// Define flag value using the `enum` syntax. See below for details.
1142 ///
1143 /// Each enumeration value **MUST** have a specified value.
1144 ///
1145 /// The width of the bitfield **MUST** also be specified by its integer type.
1146 ///
1147 /// It is important to note that the size of the flag enumeration itself is
1148 /// unrelated to the size of the corresponding `FlagSet` instance.
1149 ///
1150 /// It is also worth noting that this macro automatically implements a variety
1151 /// of standard traits including:
1152 ///   * Copy
1153 ///   * Clone
1154 ///   * Debug
1155 ///   * PartialEq
1156 ///   * Eq
1157 ///   * From<$enum> for $integer
1158 ///   * Not
1159 ///   * BitAnd
1160 ///   * BitOr
1161 ///   * BitXor
1162 ///   * Sub
1163 ///   * Rem
1164 ///
1165 /// ```
1166 /// use std::mem::{align_of, size_of};
1167 /// use flagset::{FlagSet, flags};
1168 ///
1169 /// flags! {
1170 ///     enum FlagEmpty: u32 {}
1171 ///
1172 ///     enum Flag8: u8 {
1173 ///         Foo = 0b001,
1174 ///         Bar = 0b010,
1175 ///         Baz = 0b100
1176 ///     }
1177 ///
1178 ///     pub enum Flag16: u16 {
1179 ///         Foo,
1180 ///         Bar,
1181 ///         #[deprecated]
1182 ///         Baz,
1183 ///     }
1184 ///
1185 ///     #[derive(PartialOrd, Ord)]
1186 ///     enum Flag32: u32 {
1187 ///         Foo = 0b001,
1188 ///         #[deprecated]
1189 ///         Bar = 0b010,
1190 ///         Baz = 0b100
1191 ///     }
1192 ///
1193 ///     #[repr(u64)]
1194 ///     enum Flag64: u64 {
1195 ///         Foo = 0b001,
1196 ///         Bar = 0b010,
1197 ///         Baz = 0b100
1198 ///     }
1199 ///
1200 ///     #[repr(u32)]
1201 ///     enum Flag128: u128 {
1202 ///         Foo = 0b001,
1203 ///         Bar = 0b010,
1204 ///         Baz = 0b100
1205 ///     }
1206 /// }
1207 ///
1208 /// assert_eq!(size_of::<Flag8>(), 1);
1209 /// assert_eq!(size_of::<Flag16>(), 1);
1210 /// assert_eq!(size_of::<Flag32>(), 1);
1211 /// assert_eq!(size_of::<Flag64>(), 8);
1212 /// assert_eq!(size_of::<Flag128>(), 4);
1213 ///
1214 /// assert_eq!(align_of::<Flag8>(), 1);
1215 /// assert_eq!(align_of::<Flag16>(), 1);
1216 /// assert_eq!(align_of::<Flag32>(), 1);
1217 /// assert_eq!(align_of::<Flag64>(), align_of::<u64>());
1218 /// assert_eq!(align_of::<Flag128>(), align_of::<u32>());
1219 ///
1220 /// assert_eq!(size_of::<FlagSet<Flag8>>(), size_of::<u8>());
1221 /// assert_eq!(size_of::<FlagSet<Flag16>>(), size_of::<u16>());
1222 /// assert_eq!(size_of::<FlagSet<Flag32>>(), size_of::<u32>());
1223 /// assert_eq!(size_of::<FlagSet<Flag64>>(), size_of::<u64>());
1224 /// assert_eq!(size_of::<FlagSet<Flag128>>(), size_of::<u128>());
1225 ///
1226 /// assert_eq!(align_of::<FlagSet<Flag8>>(), align_of::<u8>());
1227 /// assert_eq!(align_of::<FlagSet<Flag16>>(), align_of::<u16>());
1228 /// assert_eq!(align_of::<FlagSet<Flag32>>(), align_of::<u32>());
1229 /// assert_eq!(align_of::<FlagSet<Flag64>>(), align_of::<u64>());
1230 /// assert_eq!(align_of::<FlagSet<Flag128>>(), align_of::<u128>());
1231 /// ```
1232 #[macro_export]
1233 macro_rules! flags {
1234     () => {};
1235 
1236     // Entry point for enumerations without values.
1237     ($(#[$m:meta])* $p:vis enum $n:ident: $t:ty { $($(#[$a:meta])* $k:ident),+ $(,)* } $($next:tt)*) => {
1238         $crate::flags! { $(#[$m])* $p enum $n: $t { $($(#[$a])* $k = (1 << $n::$k as $t)),+ } $($next)* }
1239     };
1240 
1241     // Entrypoint for enumerations with values.
1242     ($(#[$m:meta])* $p:vis enum $n:ident: $t:ty { $($(#[$a:meta])*$k:ident = $v:expr),* $(,)* } $($next:tt)*) => {
1243         $(#[$m])*
1244         #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1245         $p enum $n { $($(#[$a])* $k),* }
1246 
1247         impl $crate::Flags for $n {
1248             type Type = $t;
1249 
1250             const LIST: &'static [Self] = &[$($n::$k),*];
1251         }
1252 
1253         impl ::core::convert::From<$n> for $crate::FlagSet<$n> {
1254             #[inline]
1255             fn from(value: $n) -> Self {
1256                 unsafe {
1257                     match value {
1258                         $($n::$k => Self::new_unchecked($v)),*
1259                     }
1260                 }
1261             }
1262         }
1263 
1264         impl ::core::ops::Not for $n {
1265             type Output = $crate::FlagSet<$n>;
1266 
1267             #[inline]
1268             fn not(self) -> Self::Output {
1269                 !$crate::FlagSet::from(self)
1270             }
1271         }
1272 
1273         impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::BitAnd<R> for $n {
1274             type Output = $crate::FlagSet<$n>;
1275 
1276             #[inline]
1277             fn bitand(self, rhs: R) -> Self::Output {
1278                 $crate::FlagSet::from(self) & rhs
1279             }
1280         }
1281 
1282         impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::BitOr<R> for $n {
1283             type Output = $crate::FlagSet<$n>;
1284 
1285             #[inline]
1286             fn bitor(self, rhs: R) -> Self::Output {
1287                 $crate::FlagSet::from(self) | rhs
1288             }
1289         }
1290 
1291         impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::BitXor<R> for $n {
1292             type Output = $crate::FlagSet<$n>;
1293 
1294             #[inline]
1295             fn bitxor(self, rhs: R) -> Self::Output {
1296                 $crate::FlagSet::from(self) ^ rhs
1297             }
1298         }
1299 
1300         impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::Sub<R> for $n {
1301             type Output = $crate::FlagSet<$n>;
1302 
1303             #[inline]
1304             fn sub(self, rhs: R) -> Self::Output {
1305                 $crate::FlagSet::from(self) - rhs
1306             }
1307         }
1308 
1309         impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::Rem<R> for $n {
1310             type Output = $crate::FlagSet<$n>;
1311 
1312             #[inline]
1313             fn rem(self, rhs: R) -> Self::Output {
1314                 $crate::FlagSet::from(self) % rhs
1315             }
1316         }
1317 
1318         $crate::flags! { $($next)* }
1319     };
1320 }
1321