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}