flagset/
lib.rs

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