blob: 36c0699ed79acbb99d12be010dff354b69a767c9 [file] [log] [blame]
Jason Macnakefaa0952019-12-12 22:33:33 +00001// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! A typesafe bitmask flag generator useful for sets of C-style bitmask flags.
12//! It can be used for creating typesafe wrappers around C APIs.
13//!
Joel Galensonf9c300d2021-09-22 14:30:25 -070014//! The `bitflags!` macro generates `struct`s that manage a set of flags. The
Jason Macnakefaa0952019-12-12 22:33:33 +000015//! flags should only be defined for integer types, otherwise unexpected type
16//! errors may occur at compile time.
17//!
18//! # Example
19//!
20//! ```
Joel Galensonf9c300d2021-09-22 14:30:25 -070021//! use bitflags::bitflags;
Jason Macnakefaa0952019-12-12 22:33:33 +000022//!
23//! bitflags! {
24//! struct Flags: u32 {
25//! const A = 0b00000001;
26//! const B = 0b00000010;
27//! const C = 0b00000100;
28//! const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
29//! }
30//! }
31//!
32//! fn main() {
33//! let e1 = Flags::A | Flags::C;
34//! let e2 = Flags::B | Flags::C;
35//! assert_eq!((e1 | e2), Flags::ABC); // union
36//! assert_eq!((e1 & e2), Flags::C); // intersection
37//! assert_eq!((e1 - e2), Flags::A); // set difference
38//! assert_eq!(!e2, Flags::A); // set complement
39//! }
40//! ```
41//!
42//! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code
43//! generated by the above `bitflags!` expansion.
44//!
45//! The generated `struct`s can also be extended with type and trait
46//! implementations:
47//!
48//! ```
Jason Macnakefaa0952019-12-12 22:33:33 +000049//! use std::fmt;
50//!
Joel Galensonf9c300d2021-09-22 14:30:25 -070051//! use bitflags::bitflags;
52//!
Jason Macnakefaa0952019-12-12 22:33:33 +000053//! bitflags! {
54//! struct Flags: u32 {
55//! const A = 0b00000001;
56//! const B = 0b00000010;
57//! }
58//! }
59//!
60//! impl Flags {
61//! pub fn clear(&mut self) {
62//! self.bits = 0; // The `bits` field can be accessed from within the
63//! // same module where the `bitflags!` macro was invoked.
64//! }
65//! }
66//!
67//! impl fmt::Display for Flags {
68//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69//! write!(f, "hi!")
70//! }
71//! }
72//!
73//! fn main() {
74//! let mut flags = Flags::A | Flags::B;
75//! flags.clear();
76//! assert!(flags.is_empty());
77//! assert_eq!(format!("{}", flags), "hi!");
78//! assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
79//! assert_eq!(format!("{:?}", Flags::B), "B");
80//! }
81//! ```
82//!
83//! # Visibility
84//!
Joel Galensonf9c300d2021-09-22 14:30:25 -070085//! The generated structs and their associated flag constants are not exported
Jason Macnakefaa0952019-12-12 22:33:33 +000086//! out of the current module by default. A definition can be exported out of
Joel Galensonf9c300d2021-09-22 14:30:25 -070087//! the current module by adding `pub` before `struct`:
Jason Macnakefaa0952019-12-12 22:33:33 +000088//!
89//! ```
Jason Macnakefaa0952019-12-12 22:33:33 +000090//! mod example {
Joel Galensonf9c300d2021-09-22 14:30:25 -070091//! use bitflags::bitflags;
92//!
Jason Macnakefaa0952019-12-12 22:33:33 +000093//! bitflags! {
94//! pub struct Flags1: u32 {
95//! const A = 0b00000001;
96//! }
Joel Galensonf9c300d2021-09-22 14:30:25 -070097//!
Jason Macnakefaa0952019-12-12 22:33:33 +000098//! # pub
99//! struct Flags2: u32 {
100//! const B = 0b00000010;
101//! }
102//! }
103//! }
104//!
105//! fn main() {
106//! let flag1 = example::Flags1::A;
107//! let flag2 = example::Flags2::B; // error: const `B` is private
108//! }
109//! ```
110//!
111//! # Attributes
112//!
Joel Galensonf9c300d2021-09-22 14:30:25 -0700113//! Attributes can be attached to the generated `struct`s by placing them
114//! before the `struct` keyword.
115//!
116//! ## Representations
117//!
118//! It's valid to add a `#[repr(C)]` or `#[repr(transparent)]` attribute to a type
119//! generated by `bitflags!`. In these cases, the type is guaranteed to be a newtype.
120//!
121//! ```
122//! use bitflags::bitflags;
123//!
124//! bitflags! {
125//! #[repr(transparent)]
126//! struct Flags: u32 {
127//! const A = 0b00000001;
128//! const B = 0b00000010;
129//! const C = 0b00000100;
130//! }
131//! }
132//! ```
Jason Macnakefaa0952019-12-12 22:33:33 +0000133//!
134//! # Trait implementations
135//!
136//! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash`
Joel Galensonf9c300d2021-09-22 14:30:25 -0700137//! traits are automatically derived for the `struct`s using the `derive` attribute.
Jason Macnakefaa0952019-12-12 22:33:33 +0000138//! Additional traits can be derived by providing an explicit `derive`
Joel Galensonf9c300d2021-09-22 14:30:25 -0700139//! attribute on `struct`.
Jason Macnakefaa0952019-12-12 22:33:33 +0000140//!
Joel Galensonf9c300d2021-09-22 14:30:25 -0700141//! The `Extend` and `FromIterator` traits are implemented for the `struct`s,
Jason Macnakefaa0952019-12-12 22:33:33 +0000142//! too: `Extend` adds the union of the instances of the `struct` iterated over,
143//! while `FromIterator` calculates the union.
144//!
Joel Galensonf9c300d2021-09-22 14:30:25 -0700145//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` traits are also
Jason Macnakefaa0952019-12-12 22:33:33 +0000146//! implemented by displaying the bits value of the internal struct.
147//!
148//! ## Operators
149//!
Joel Galensonf9c300d2021-09-22 14:30:25 -0700150//! The following operator traits are implemented for the generated `struct`s:
Jason Macnakefaa0952019-12-12 22:33:33 +0000151//!
152//! - `BitOr` and `BitOrAssign`: union
153//! - `BitAnd` and `BitAndAssign`: intersection
154//! - `BitXor` and `BitXorAssign`: toggle
155//! - `Sub` and `SubAssign`: set difference
156//! - `Not`: set complement
157//!
158//! # Methods
159//!
Joel Galensonf9c300d2021-09-22 14:30:25 -0700160//! The following methods are defined for the generated `struct`s:
Jason Macnakefaa0952019-12-12 22:33:33 +0000161//!
162//! - `empty`: an empty set of flags
163//! - `all`: the set of all defined flags
164//! - `bits`: the raw value of the flags currently stored
165//! - `from_bits`: convert from underlying bit representation, unless that
166//! representation contains bits that do not correspond to a
167//! defined flag
168//! - `from_bits_truncate`: convert from underlying bit representation, dropping
169//! any bits that do not correspond to defined flags
170//! - `from_bits_unchecked`: convert from underlying bit representation, keeping
171//! all bits (even those not corresponding to defined
172//! flags)
173//! - `is_empty`: `true` if no flags are currently stored
174//! - `is_all`: `true` if currently set flags exactly equal all defined flags
175//! - `intersects`: `true` if there are flags common to both `self` and `other`
Joel Galensonf9c300d2021-09-22 14:30:25 -0700176//! - `contains`: `true` if all of the flags in `other` are contained within `self`
Jason Macnakefaa0952019-12-12 22:33:33 +0000177//! - `insert`: inserts the specified flags in-place
178//! - `remove`: removes the specified flags in-place
179//! - `toggle`: the specified flags will be inserted if not present, and removed
180//! if they are.
181//! - `set`: inserts or removes the specified flags depending on the passed value
Joel Galensonf9c300d2021-09-22 14:30:25 -0700182//! - `intersection`: returns a new set of flags, containing only the flags present
183//! in both `self` and `other` (the argument to the function).
184//! - `union`: returns a new set of flags, containing any flags present in
185//! either `self` or `other` (the argument to the function).
186//! - `difference`: returns a new set of flags, containing all flags present in
187//! `self` without any of the flags present in `other` (the
188//! argument to the function).
189//! - `symmetric_difference`: returns a new set of flags, containing all flags
190//! present in either `self` or `other` (the argument
191//! to the function), but not both.
192//! - `complement`: returns a new set of flags, containing all flags which are
193//! not set in `self`, but which are allowed for this type.
Jason Macnakefaa0952019-12-12 22:33:33 +0000194//!
195//! ## Default
196//!
Joel Galensonf9c300d2021-09-22 14:30:25 -0700197//! The `Default` trait is not automatically implemented for the generated structs.
Jason Macnakefaa0952019-12-12 22:33:33 +0000198//!
199//! If your default value is equal to `0` (which is the same value as calling `empty()`
200//! on the generated struct), you can simply derive `Default`:
201//!
202//! ```
Joel Galensonf9c300d2021-09-22 14:30:25 -0700203//! use bitflags::bitflags;
Jason Macnakefaa0952019-12-12 22:33:33 +0000204//!
205//! bitflags! {
206//! // Results in default value with bits: 0
207//! #[derive(Default)]
208//! struct Flags: u32 {
209//! const A = 0b00000001;
210//! const B = 0b00000010;
211//! const C = 0b00000100;
212//! }
213//! }
214//!
215//! fn main() {
216//! let derived_default: Flags = Default::default();
217//! assert_eq!(derived_default.bits(), 0);
218//! }
219//! ```
220//!
221//! If your default value is not equal to `0` you need to implement `Default` yourself:
222//!
223//! ```
Joel Galensonf9c300d2021-09-22 14:30:25 -0700224//! use bitflags::bitflags;
Jason Macnakefaa0952019-12-12 22:33:33 +0000225//!
226//! bitflags! {
227//! struct Flags: u32 {
228//! const A = 0b00000001;
229//! const B = 0b00000010;
230//! const C = 0b00000100;
231//! }
232//! }
233//!
234//! // explicit `Default` implementation
235//! impl Default for Flags {
236//! fn default() -> Flags {
237//! Flags::A | Flags::C
238//! }
239//! }
240//!
241//! fn main() {
242//! let implemented_default: Flags = Default::default();
243//! assert_eq!(implemented_default, (Flags::A | Flags::C));
244//! }
245//! ```
246//!
247//! # Zero Flags
248//!
249//! Flags with a value equal to zero will have some strange behavior that one should be aware of.
250//!
251//! ```
Joel Galensonf9c300d2021-09-22 14:30:25 -0700252//! use bitflags::bitflags;
Jason Macnakefaa0952019-12-12 22:33:33 +0000253//!
254//! bitflags! {
255//! struct Flags: u32 {
256//! const NONE = 0b00000000;
257//! const SOME = 0b00000001;
258//! }
259//! }
260//!
261//! fn main() {
262//! let empty = Flags::empty();
263//! let none = Flags::NONE;
264//! let some = Flags::SOME;
265//!
266//! // Zero flags are treated as always present
267//! assert!(empty.contains(Flags::NONE));
268//! assert!(none.contains(Flags::NONE));
269//! assert!(some.contains(Flags::NONE));
270//!
271//! // Zero flags will be ignored when testing for emptiness
272//! assert!(none.is_empty());
273//! }
274//! ```
Joel Galensonf9c300d2021-09-22 14:30:25 -0700275//!
276//! Users should generally avoid defining a flag with a value of zero.
Jason Macnakefaa0952019-12-12 22:33:33 +0000277
Joel Galensonf9c300d2021-09-22 14:30:25 -0700278#![cfg_attr(not(test), no_std)]
279#![doc(html_root_url = "https://docs.rs/bitflags/1.3.2")]
Jason Macnakefaa0952019-12-12 22:33:33 +0000280
Matthew Maurer541fa022020-07-06 13:12:51 -0700281// ANDROID: Unconditionally use std to allow building as a dylib
Jason Macnakefaa0952019-12-12 22:33:33 +0000282#[macro_use]
283extern crate std;
284
Jason Macnakefaa0952019-12-12 22:33:33 +0000285#[doc(hidden)]
286pub extern crate core as _core;
287
Joel Galensonf9c300d2021-09-22 14:30:25 -0700288/// The macro used to generate the flag structures.
Jason Macnakefaa0952019-12-12 22:33:33 +0000289///
290/// See the [crate level docs](../bitflags/index.html) for complete documentation.
291///
292/// # Example
293///
294/// ```
Joel Galensonf9c300d2021-09-22 14:30:25 -0700295/// use bitflags::bitflags;
Jason Macnakefaa0952019-12-12 22:33:33 +0000296///
297/// bitflags! {
298/// struct Flags: u32 {
299/// const A = 0b00000001;
300/// const B = 0b00000010;
301/// const C = 0b00000100;
302/// const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
303/// }
304/// }
305///
306/// fn main() {
307/// let e1 = Flags::A | Flags::C;
308/// let e2 = Flags::B | Flags::C;
309/// assert_eq!((e1 | e2), Flags::ABC); // union
310/// assert_eq!((e1 & e2), Flags::C); // intersection
311/// assert_eq!((e1 - e2), Flags::A); // set difference
312/// assert_eq!(!e2, Flags::A); // set complement
313/// }
314/// ```
315///
316/// The generated `struct`s can also be extended with type and trait
317/// implementations:
318///
319/// ```
Jason Macnakefaa0952019-12-12 22:33:33 +0000320/// use std::fmt;
321///
Joel Galensonf9c300d2021-09-22 14:30:25 -0700322/// use bitflags::bitflags;
323///
Jason Macnakefaa0952019-12-12 22:33:33 +0000324/// bitflags! {
325/// struct Flags: u32 {
326/// const A = 0b00000001;
327/// const B = 0b00000010;
328/// }
329/// }
330///
331/// impl Flags {
332/// pub fn clear(&mut self) {
333/// self.bits = 0; // The `bits` field can be accessed from within the
334/// // same module where the `bitflags!` macro was invoked.
335/// }
336/// }
337///
338/// impl fmt::Display for Flags {
339/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
340/// write!(f, "hi!")
341/// }
342/// }
343///
344/// fn main() {
345/// let mut flags = Flags::A | Flags::B;
346/// flags.clear();
347/// assert!(flags.is_empty());
348/// assert_eq!(format!("{}", flags), "hi!");
349/// assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
350/// assert_eq!(format!("{:?}", Flags::B), "B");
351/// }
352/// ```
353#[macro_export(local_inner_macros)]
354macro_rules! bitflags {
355 (
356 $(#[$outer:meta])*
Joel Galensonf9c300d2021-09-22 14:30:25 -0700357 $vis:vis struct $BitFlags:ident: $T:ty {
Jason Macnakefaa0952019-12-12 22:33:33 +0000358 $(
359 $(#[$inner:ident $($args:tt)*])*
360 const $Flag:ident = $value:expr;
Joel Galensonf9c300d2021-09-22 14:30:25 -0700361 )*
Jason Macnakefaa0952019-12-12 22:33:33 +0000362 }
Jason Macnakefaa0952019-12-12 22:33:33 +0000363
Joel Galensonf9c300d2021-09-22 14:30:25 -0700364 $($t:tt)*
Jason Macnakefaa0952019-12-12 22:33:33 +0000365 ) => {
366 $(#[$outer])*
367 #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700368 $vis struct $BitFlags {
Jason Macnakefaa0952019-12-12 22:33:33 +0000369 bits: $T,
370 }
371
372 __impl_bitflags! {
373 $BitFlags: $T {
374 $(
375 $(#[$inner $($args)*])*
376 $Flag = $value;
Joel Galensonf9c300d2021-09-22 14:30:25 -0700377 )*
Jason Macnakefaa0952019-12-12 22:33:33 +0000378 }
379 }
Joel Galensonf9c300d2021-09-22 14:30:25 -0700380
381 bitflags! {
382 $($t)*
383 }
Jason Macnakefaa0952019-12-12 22:33:33 +0000384 };
Joel Galensonf9c300d2021-09-22 14:30:25 -0700385 () => {};
Jason Macnakefaa0952019-12-12 22:33:33 +0000386}
387
Joel Galensonf9c300d2021-09-22 14:30:25 -0700388// A helper macro to implement the `all` function.
Jason Macnakefaa0952019-12-12 22:33:33 +0000389#[macro_export(local_inner_macros)]
390#[doc(hidden)]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700391macro_rules! __impl_all_bitflags {
Jason Macnakefaa0952019-12-12 22:33:33 +0000392 (
Joel Galensonf9c300d2021-09-22 14:30:25 -0700393 $BitFlags:ident: $T:ty {
394 $(
395 $(#[$attr:ident $($args:tt)*])*
396 $Flag:ident = $value:expr;
397 )+
398 }
Jason Macnakefaa0952019-12-12 22:33:33 +0000399 ) => {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700400 // See `Debug::fmt` for why this approach is taken.
401 #[allow(non_snake_case)]
402 trait __BitFlags {
403 $(
404 const $Flag: $T = 0;
405 )+
406 }
407 #[allow(non_snake_case)]
408 impl __BitFlags for $BitFlags {
409 $(
410 __impl_bitflags! {
411 #[allow(deprecated)]
412 $(? #[$attr $($args)*])*
413 const $Flag: $T = Self::$Flag.bits;
414 }
415 )+
416 }
417 Self { bits: $(<Self as __BitFlags>::$Flag)|+ }
Jason Macnakefaa0952019-12-12 22:33:33 +0000418 };
419 (
Joel Galensonf9c300d2021-09-22 14:30:25 -0700420 $BitFlags:ident: $T:ty { }
Jason Macnakefaa0952019-12-12 22:33:33 +0000421 ) => {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700422 Self { bits: 0 }
Jason Macnakefaa0952019-12-12 22:33:33 +0000423 };
424}
425
426#[macro_export(local_inner_macros)]
427#[doc(hidden)]
428macro_rules! __impl_bitflags {
429 (
430 $BitFlags:ident: $T:ty {
431 $(
432 $(#[$attr:ident $($args:tt)*])*
433 $Flag:ident = $value:expr;
Joel Galensonf9c300d2021-09-22 14:30:25 -0700434 )*
Jason Macnakefaa0952019-12-12 22:33:33 +0000435 }
436 ) => {
437 impl $crate::_core::fmt::Debug for $BitFlags {
438 fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
439 // This convoluted approach is to handle #[cfg]-based flag
440 // omission correctly. For example it needs to support:
441 //
442 // #[cfg(unix)] const A: Flag = /* ... */;
443 // #[cfg(windows)] const B: Flag = /* ... */;
444
445 // Unconditionally define a check for every flag, even disabled
446 // ones.
447 #[allow(non_snake_case)]
448 trait __BitFlags {
449 $(
450 #[inline]
451 fn $Flag(&self) -> bool { false }
Joel Galensonf9c300d2021-09-22 14:30:25 -0700452 )*
Jason Macnakefaa0952019-12-12 22:33:33 +0000453 }
454
455 // Conditionally override the check for just those flags that
456 // are not #[cfg]ed away.
Joel Galensonf9c300d2021-09-22 14:30:25 -0700457 #[allow(non_snake_case)]
Jason Macnakefaa0952019-12-12 22:33:33 +0000458 impl __BitFlags for $BitFlags {
459 $(
460 __impl_bitflags! {
461 #[allow(deprecated)]
462 #[inline]
463 $(? #[$attr $($args)*])*
464 fn $Flag(&self) -> bool {
465 if Self::$Flag.bits == 0 && self.bits != 0 {
466 false
467 } else {
468 self.bits & Self::$Flag.bits == Self::$Flag.bits
469 }
470 }
471 }
Joel Galensonf9c300d2021-09-22 14:30:25 -0700472 )*
Jason Macnakefaa0952019-12-12 22:33:33 +0000473 }
474
475 let mut first = true;
476 $(
Joel Galensonf9c300d2021-09-22 14:30:25 -0700477 if <Self as __BitFlags>::$Flag(self) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000478 if !first {
479 f.write_str(" | ")?;
480 }
481 first = false;
Joel Galensonf9c300d2021-09-22 14:30:25 -0700482 f.write_str($crate::_core::stringify!($Flag))?;
Jason Macnakefaa0952019-12-12 22:33:33 +0000483 }
Joel Galensonf9c300d2021-09-22 14:30:25 -0700484 )*
485 let extra_bits = self.bits & !Self::all().bits();
Jason Macnakefaa0952019-12-12 22:33:33 +0000486 if extra_bits != 0 {
487 if !first {
488 f.write_str(" | ")?;
489 }
490 first = false;
491 f.write_str("0x")?;
492 $crate::_core::fmt::LowerHex::fmt(&extra_bits, f)?;
493 }
494 if first {
495 f.write_str("(empty)")?;
496 }
497 Ok(())
498 }
499 }
500 impl $crate::_core::fmt::Binary for $BitFlags {
501 fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
502 $crate::_core::fmt::Binary::fmt(&self.bits, f)
503 }
504 }
505 impl $crate::_core::fmt::Octal for $BitFlags {
506 fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
507 $crate::_core::fmt::Octal::fmt(&self.bits, f)
508 }
509 }
510 impl $crate::_core::fmt::LowerHex for $BitFlags {
511 fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
512 $crate::_core::fmt::LowerHex::fmt(&self.bits, f)
513 }
514 }
515 impl $crate::_core::fmt::UpperHex for $BitFlags {
516 fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
517 $crate::_core::fmt::UpperHex::fmt(&self.bits, f)
518 }
519 }
520
521 #[allow(dead_code)]
522 impl $BitFlags {
523 $(
524 $(#[$attr $($args)*])*
Joel Galensonf9c300d2021-09-22 14:30:25 -0700525 pub const $Flag: Self = Self { bits: $value };
526 )*
Jason Macnakefaa0952019-12-12 22:33:33 +0000527
Joel Galensonf9c300d2021-09-22 14:30:25 -0700528 /// Returns an empty set of flags.
529 #[inline]
530 pub const fn empty() -> Self {
531 Self { bits: 0 }
532 }
533
534 /// Returns the set containing all flags.
535 #[inline]
536 pub const fn all() -> Self {
537 __impl_all_bitflags! {
538 $BitFlags: $T {
539 $(
540 $(#[$attr $($args)*])*
541 $Flag = $value;
542 )*
543 }
Jason Macnakefaa0952019-12-12 22:33:33 +0000544 }
545 }
546
Joel Galensonf9c300d2021-09-22 14:30:25 -0700547 /// Returns the raw value of the flags currently stored.
548 #[inline]
549 pub const fn bits(&self) -> $T {
550 self.bits
Jason Macnakefaa0952019-12-12 22:33:33 +0000551 }
552
553 /// Convert from underlying bit representation, unless that
554 /// representation contains bits that do not correspond to a flag.
555 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700556 pub const fn from_bits(bits: $T) -> $crate::_core::option::Option<Self> {
557 if (bits & !Self::all().bits()) == 0 {
558 $crate::_core::option::Option::Some(Self { bits })
Jason Macnakefaa0952019-12-12 22:33:33 +0000559 } else {
560 $crate::_core::option::Option::None
561 }
562 }
563
Joel Galensonf9c300d2021-09-22 14:30:25 -0700564 /// Convert from underlying bit representation, dropping any bits
565 /// that do not correspond to flags.
566 #[inline]
567 pub const fn from_bits_truncate(bits: $T) -> Self {
568 Self { bits: bits & Self::all().bits }
Jason Macnakefaa0952019-12-12 22:33:33 +0000569 }
570
Joel Galensonf9c300d2021-09-22 14:30:25 -0700571 /// Convert from underlying bit representation, preserving all
572 /// bits (even those not corresponding to a defined flag).
573 ///
574 /// # Safety
575 ///
576 /// The caller of the `bitflags!` macro can chose to allow or
577 /// disallow extra bits for their bitflags type.
578 ///
579 /// The caller of `from_bits_unchecked()` has to ensure that
580 /// all bits correspond to a defined flag or that extra bits
581 /// are valid for this bitflags type.
582 #[inline]
583 pub const unsafe fn from_bits_unchecked(bits: $T) -> Self {
584 Self { bits }
Jason Macnakefaa0952019-12-12 22:33:33 +0000585 }
586
Joel Galensonf9c300d2021-09-22 14:30:25 -0700587 /// Returns `true` if no flags are currently stored.
588 #[inline]
589 pub const fn is_empty(&self) -> bool {
590 self.bits() == Self::empty().bits()
Jason Macnakefaa0952019-12-12 22:33:33 +0000591 }
592
Joel Galensonf9c300d2021-09-22 14:30:25 -0700593 /// Returns `true` if all flags are currently set.
594 #[inline]
595 pub const fn is_all(&self) -> bool {
596 Self::all().bits | self.bits == self.bits
Jason Macnakefaa0952019-12-12 22:33:33 +0000597 }
598
Joel Galensonf9c300d2021-09-22 14:30:25 -0700599 /// Returns `true` if there are flags common to both `self` and `other`.
600 #[inline]
601 pub const fn intersects(&self, other: Self) -> bool {
602 !(Self { bits: self.bits & other.bits}).is_empty()
Jason Macnakefaa0952019-12-12 22:33:33 +0000603 }
604
Joel Galensonf9c300d2021-09-22 14:30:25 -0700605 /// Returns `true` if all of the flags in `other` are contained within `self`.
606 #[inline]
607 pub const fn contains(&self, other: Self) -> bool {
608 (self.bits & other.bits) == other.bits
Jason Macnakefaa0952019-12-12 22:33:33 +0000609 }
610
611 /// Inserts the specified flags in-place.
612 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700613 pub fn insert(&mut self, other: Self) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000614 self.bits |= other.bits;
615 }
616
617 /// Removes the specified flags in-place.
618 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700619 pub fn remove(&mut self, other: Self) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000620 self.bits &= !other.bits;
621 }
622
623 /// Toggles the specified flags in-place.
624 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700625 pub fn toggle(&mut self, other: Self) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000626 self.bits ^= other.bits;
627 }
628
629 /// Inserts or removes the specified flags depending on the passed value.
630 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700631 pub fn set(&mut self, other: Self, value: bool) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000632 if value {
633 self.insert(other);
634 } else {
635 self.remove(other);
636 }
637 }
Joel Galensonf9c300d2021-09-22 14:30:25 -0700638
639 /// Returns the intersection between the flags in `self` and
640 /// `other`.
641 ///
642 /// Specifically, the returned set contains only the flags which are
643 /// present in *both* `self` *and* `other`.
644 ///
645 /// This is equivalent to using the `&` operator (e.g.
646 /// [`ops::BitAnd`]), as in `flags & other`.
647 ///
648 /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
649 #[inline]
650 #[must_use]
651 pub const fn intersection(self, other: Self) -> Self {
652 Self { bits: self.bits & other.bits }
653 }
654
655 /// Returns the union of between the flags in `self` and `other`.
656 ///
657 /// Specifically, the returned set contains all flags which are
658 /// present in *either* `self` *or* `other`, including any which are
659 /// present in both (see [`Self::symmetric_difference`] if that
660 /// is undesirable).
661 ///
662 /// This is equivalent to using the `|` operator (e.g.
663 /// [`ops::BitOr`]), as in `flags | other`.
664 ///
665 /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
666 #[inline]
667 #[must_use]
668 pub const fn union(self, other: Self) -> Self {
669 Self { bits: self.bits | other.bits }
670 }
671
672 /// Returns the difference between the flags in `self` and `other`.
673 ///
674 /// Specifically, the returned set contains all flags present in
675 /// `self`, except for the ones present in `other`.
676 ///
677 /// It is also conceptually equivalent to the "bit-clear" operation:
678 /// `flags & !other` (and this syntax is also supported).
679 ///
680 /// This is equivalent to using the `-` operator (e.g.
681 /// [`ops::Sub`]), as in `flags - other`.
682 ///
683 /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
684 #[inline]
685 #[must_use]
686 pub const fn difference(self, other: Self) -> Self {
687 Self { bits: self.bits & !other.bits }
688 }
689
690 /// Returns the [symmetric difference][sym-diff] between the flags
691 /// in `self` and `other`.
692 ///
693 /// Specifically, the returned set contains the flags present which
694 /// are present in `self` or `other`, but that are not present in
695 /// both. Equivalently, it contains the flags present in *exactly
696 /// one* of the sets `self` and `other`.
697 ///
698 /// This is equivalent to using the `^` operator (e.g.
699 /// [`ops::BitXor`]), as in `flags ^ other`.
700 ///
701 /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference
702 /// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
703 #[inline]
704 #[must_use]
705 pub const fn symmetric_difference(self, other: Self) -> Self {
706 Self { bits: self.bits ^ other.bits }
707 }
708
709 /// Returns the complement of this set of flags.
710 ///
711 /// Specifically, the returned set contains all the flags which are
712 /// not set in `self`, but which are allowed for this type.
713 ///
714 /// Alternatively, it can be thought of as the set difference
715 /// between [`Self::all()`] and `self` (e.g. `Self::all() - self`)
716 ///
717 /// This is equivalent to using the `!` operator (e.g.
718 /// [`ops::Not`]), as in `!flags`.
719 ///
720 /// [`Self::all()`]: Self::all
721 /// [`ops::Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html
722 #[inline]
723 #[must_use]
724 pub const fn complement(self) -> Self {
725 Self::from_bits_truncate(!self.bits)
726 }
727
Jason Macnakefaa0952019-12-12 22:33:33 +0000728 }
729
730 impl $crate::_core::ops::BitOr for $BitFlags {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700731 type Output = Self;
Jason Macnakefaa0952019-12-12 22:33:33 +0000732
733 /// Returns the union of the two sets of flags.
734 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700735 fn bitor(self, other: $BitFlags) -> Self {
736 Self { bits: self.bits | other.bits }
Jason Macnakefaa0952019-12-12 22:33:33 +0000737 }
738 }
739
740 impl $crate::_core::ops::BitOrAssign for $BitFlags {
Jason Macnakefaa0952019-12-12 22:33:33 +0000741 /// Adds the set of flags.
742 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700743 fn bitor_assign(&mut self, other: Self) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000744 self.bits |= other.bits;
745 }
746 }
747
748 impl $crate::_core::ops::BitXor for $BitFlags {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700749 type Output = Self;
Jason Macnakefaa0952019-12-12 22:33:33 +0000750
751 /// Returns the left flags, but with all the right flags toggled.
752 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700753 fn bitxor(self, other: Self) -> Self {
754 Self { bits: self.bits ^ other.bits }
Jason Macnakefaa0952019-12-12 22:33:33 +0000755 }
756 }
757
758 impl $crate::_core::ops::BitXorAssign for $BitFlags {
Jason Macnakefaa0952019-12-12 22:33:33 +0000759 /// Toggles the set of flags.
760 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700761 fn bitxor_assign(&mut self, other: Self) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000762 self.bits ^= other.bits;
763 }
764 }
765
766 impl $crate::_core::ops::BitAnd for $BitFlags {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700767 type Output = Self;
Jason Macnakefaa0952019-12-12 22:33:33 +0000768
769 /// Returns the intersection between the two sets of flags.
770 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700771 fn bitand(self, other: Self) -> Self {
772 Self { bits: self.bits & other.bits }
Jason Macnakefaa0952019-12-12 22:33:33 +0000773 }
774 }
775
776 impl $crate::_core::ops::BitAndAssign for $BitFlags {
Jason Macnakefaa0952019-12-12 22:33:33 +0000777 /// Disables all flags disabled in the set.
778 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700779 fn bitand_assign(&mut self, other: Self) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000780 self.bits &= other.bits;
781 }
782 }
783
784 impl $crate::_core::ops::Sub for $BitFlags {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700785 type Output = Self;
Jason Macnakefaa0952019-12-12 22:33:33 +0000786
787 /// Returns the set difference of the two sets of flags.
788 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700789 fn sub(self, other: Self) -> Self {
790 Self { bits: self.bits & !other.bits }
Jason Macnakefaa0952019-12-12 22:33:33 +0000791 }
792 }
793
794 impl $crate::_core::ops::SubAssign for $BitFlags {
Jason Macnakefaa0952019-12-12 22:33:33 +0000795 /// Disables all flags enabled in the set.
796 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700797 fn sub_assign(&mut self, other: Self) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000798 self.bits &= !other.bits;
799 }
800 }
801
802 impl $crate::_core::ops::Not for $BitFlags {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700803 type Output = Self;
Jason Macnakefaa0952019-12-12 22:33:33 +0000804
805 /// Returns the complement of this set of flags.
806 #[inline]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700807 fn not(self) -> Self {
808 Self { bits: !self.bits } & Self::all()
Jason Macnakefaa0952019-12-12 22:33:33 +0000809 }
810 }
811
812 impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700813 fn extend<T: $crate::_core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) {
Jason Macnakefaa0952019-12-12 22:33:33 +0000814 for item in iterator {
815 self.insert(item)
816 }
817 }
818 }
819
820 impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700821 fn from_iter<T: $crate::_core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self {
Jason Macnakefaa0952019-12-12 22:33:33 +0000822 let mut result = Self::empty();
823 result.extend(iterator);
824 result
825 }
826 }
827 };
828
829 // Every attribute that the user writes on a const is applied to the
830 // corresponding const that we generate, but within the implementation of
831 // Debug and all() we want to ignore everything but #[cfg] attributes. In
832 // particular, including a #[deprecated] attribute on those items would fail
833 // to compile.
834 // https://github.com/bitflags/bitflags/issues/109
835 //
836 // Input:
837 //
838 // ? #[cfg(feature = "advanced")]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700839 // ? #[deprecated(note = "Use something else.")]
Jason Macnakefaa0952019-12-12 22:33:33 +0000840 // ? #[doc = r"High quality documentation."]
841 // fn f() -> i32 { /* ... */ }
842 //
843 // Output:
844 //
845 // #[cfg(feature = "advanced")]
846 // fn f() -> i32 { /* ... */ }
847 (
848 $(#[$filtered:meta])*
849 ? #[cfg $($cfgargs:tt)*]
850 $(? #[$rest:ident $($restargs:tt)*])*
851 fn $($item:tt)*
852 ) => {
853 __impl_bitflags! {
854 $(#[$filtered])*
855 #[cfg $($cfgargs)*]
856 $(? #[$rest $($restargs)*])*
857 fn $($item)*
858 }
859 };
860 (
861 $(#[$filtered:meta])*
862 // $next != `cfg`
863 ? #[$next:ident $($nextargs:tt)*]
864 $(? #[$rest:ident $($restargs:tt)*])*
865 fn $($item:tt)*
866 ) => {
867 __impl_bitflags! {
868 $(#[$filtered])*
869 // $next filtered out
870 $(? #[$rest $($restargs)*])*
871 fn $($item)*
872 }
873 };
874 (
875 $(#[$filtered:meta])*
876 fn $($item:tt)*
877 ) => {
878 $(#[$filtered])*
879 fn $($item)*
880 };
881
882 // Every attribute that the user writes on a const is applied to the
883 // corresponding const that we generate, but within the implementation of
884 // Debug and all() we want to ignore everything but #[cfg] attributes. In
885 // particular, including a #[deprecated] attribute on those items would fail
886 // to compile.
887 // https://github.com/bitflags/bitflags/issues/109
888 //
889 // const version
890 //
891 // Input:
892 //
893 // ? #[cfg(feature = "advanced")]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700894 // ? #[deprecated(note = "Use something else.")]
Jason Macnakefaa0952019-12-12 22:33:33 +0000895 // ? #[doc = r"High quality documentation."]
896 // const f: i32 { /* ... */ }
897 //
898 // Output:
899 //
900 // #[cfg(feature = "advanced")]
901 // const f: i32 { /* ... */ }
902 (
903 $(#[$filtered:meta])*
904 ? #[cfg $($cfgargs:tt)*]
905 $(? #[$rest:ident $($restargs:tt)*])*
906 const $($item:tt)*
907 ) => {
908 __impl_bitflags! {
909 $(#[$filtered])*
910 #[cfg $($cfgargs)*]
911 $(? #[$rest $($restargs)*])*
912 const $($item)*
913 }
914 };
915 (
916 $(#[$filtered:meta])*
917 // $next != `cfg`
918 ? #[$next:ident $($nextargs:tt)*]
919 $(? #[$rest:ident $($restargs:tt)*])*
920 const $($item:tt)*
921 ) => {
922 __impl_bitflags! {
923 $(#[$filtered])*
924 // $next filtered out
925 $(? #[$rest $($restargs)*])*
926 const $($item)*
927 }
928 };
929 (
930 $(#[$filtered:meta])*
931 const $($item:tt)*
932 ) => {
933 $(#[$filtered])*
934 const $($item)*
935 };
936}
937
Jason Macnakefaa0952019-12-12 22:33:33 +0000938#[cfg(feature = "example_generated")]
939pub mod example_generated;
940
941#[cfg(test)]
942mod tests {
943 use std::collections::hash_map::DefaultHasher;
944 use std::hash::{Hash, Hasher};
945
946 bitflags! {
947 #[doc = "> The first principle is that you must not fool yourself — and"]
948 #[doc = "> you are the easiest person to fool."]
949 #[doc = "> "]
950 #[doc = "> - Richard Feynman"]
Joel Galensonf9c300d2021-09-22 14:30:25 -0700951 #[derive(Default)]
Jason Macnakefaa0952019-12-12 22:33:33 +0000952 struct Flags: u32 {
953 const A = 0b00000001;
954 #[doc = "<pcwalton> macros are way better at generating code than trans is"]
955 const B = 0b00000010;
956 const C = 0b00000100;
957 #[doc = "* cmr bed"]
958 #[doc = "* strcat table"]
959 #[doc = "<strcat> wait what?"]
960 const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
961 }
Jason Macnakefaa0952019-12-12 22:33:33 +0000962
Jason Macnakefaa0952019-12-12 22:33:33 +0000963 struct _CfgFlags: u32 {
964 #[cfg(unix)]
965 const _CFG_A = 0b01;
966 #[cfg(windows)]
967 const _CFG_B = 0b01;
968 #[cfg(unix)]
969 const _CFG_C = Self::_CFG_A.bits | 0b10;
970 }
Jason Macnakefaa0952019-12-12 22:33:33 +0000971
Jason Macnakefaa0952019-12-12 22:33:33 +0000972 struct AnotherSetOfFlags: i8 {
973 const ANOTHER_FLAG = -1_i8;
974 }
Joel Galensonf9c300d2021-09-22 14:30:25 -0700975
976 struct LongFlags: u32 {
977 const LONG_A = 0b1111111111111111;
978 }
Jason Macnakefaa0952019-12-12 22:33:33 +0000979 }
980
981 bitflags! {
Joel Galensonf9c300d2021-09-22 14:30:25 -0700982 struct EmptyFlags: u32 {
Jason Macnakefaa0952019-12-12 22:33:33 +0000983 }
984 }
985
986 #[test]
987 fn test_bits() {
988 assert_eq!(Flags::empty().bits(), 0b00000000);
989 assert_eq!(Flags::A.bits(), 0b00000001);
990 assert_eq!(Flags::ABC.bits(), 0b00000111);
991
992 assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
993 assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8);
Joel Galensonf9c300d2021-09-22 14:30:25 -0700994
995 assert_eq!(EmptyFlags::empty().bits(), 0b00000000);
Jason Macnakefaa0952019-12-12 22:33:33 +0000996 }
997
998 #[test]
999 fn test_from_bits() {
1000 assert_eq!(Flags::from_bits(0), Some(Flags::empty()));
1001 assert_eq!(Flags::from_bits(0b1), Some(Flags::A));
1002 assert_eq!(Flags::from_bits(0b10), Some(Flags::B));
1003 assert_eq!(Flags::from_bits(0b11), Some(Flags::A | Flags::B));
1004 assert_eq!(Flags::from_bits(0b1000), None);
1005
1006 assert_eq!(
1007 AnotherSetOfFlags::from_bits(!0_i8),
1008 Some(AnotherSetOfFlags::ANOTHER_FLAG)
1009 );
Joel Galensonf9c300d2021-09-22 14:30:25 -07001010
1011 assert_eq!(EmptyFlags::from_bits(0), Some(EmptyFlags::empty()));
1012 assert_eq!(EmptyFlags::from_bits(0b1), None);
Jason Macnakefaa0952019-12-12 22:33:33 +00001013 }
1014
1015 #[test]
1016 fn test_from_bits_truncate() {
1017 assert_eq!(Flags::from_bits_truncate(0), Flags::empty());
1018 assert_eq!(Flags::from_bits_truncate(0b1), Flags::A);
1019 assert_eq!(Flags::from_bits_truncate(0b10), Flags::B);
1020 assert_eq!(Flags::from_bits_truncate(0b11), (Flags::A | Flags::B));
1021 assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty());
1022 assert_eq!(Flags::from_bits_truncate(0b1001), Flags::A);
1023
1024 assert_eq!(
1025 AnotherSetOfFlags::from_bits_truncate(0_i8),
1026 AnotherSetOfFlags::empty()
1027 );
Joel Galensonf9c300d2021-09-22 14:30:25 -07001028
1029 assert_eq!(EmptyFlags::from_bits_truncate(0), EmptyFlags::empty());
1030 assert_eq!(EmptyFlags::from_bits_truncate(0b1), EmptyFlags::empty());
Jason Macnakefaa0952019-12-12 22:33:33 +00001031 }
1032
1033 #[test]
1034 fn test_from_bits_unchecked() {
1035 let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
1036 assert_eq!(unsafe { Flags::from_bits_unchecked(0) }, Flags::empty());
1037 assert_eq!(unsafe { Flags::from_bits_unchecked(0b1) }, Flags::A);
1038 assert_eq!(unsafe { Flags::from_bits_unchecked(0b10) }, Flags::B);
Joel Galensonf9c300d2021-09-22 14:30:25 -07001039
1040 assert_eq!(
1041 unsafe { Flags::from_bits_unchecked(0b11) },
1042 (Flags::A | Flags::B)
1043 );
1044 assert_eq!(
1045 unsafe { Flags::from_bits_unchecked(0b1000) },
1046 (extra | Flags::empty())
1047 );
1048 assert_eq!(
1049 unsafe { Flags::from_bits_unchecked(0b1001) },
1050 (extra | Flags::A)
1051 );
1052
1053 let extra = unsafe { EmptyFlags::from_bits_unchecked(0b1000) };
1054 assert_eq!(
1055 unsafe { EmptyFlags::from_bits_unchecked(0b1000) },
1056 (extra | EmptyFlags::empty())
1057 );
Jason Macnakefaa0952019-12-12 22:33:33 +00001058 }
1059
1060 #[test]
1061 fn test_is_empty() {
1062 assert!(Flags::empty().is_empty());
1063 assert!(!Flags::A.is_empty());
1064 assert!(!Flags::ABC.is_empty());
1065
1066 assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty());
Joel Galensonf9c300d2021-09-22 14:30:25 -07001067
1068 assert!(EmptyFlags::empty().is_empty());
1069 assert!(EmptyFlags::all().is_empty());
Jason Macnakefaa0952019-12-12 22:33:33 +00001070 }
1071
1072 #[test]
1073 fn test_is_all() {
1074 assert!(Flags::all().is_all());
1075 assert!(!Flags::A.is_all());
1076 assert!(Flags::ABC.is_all());
1077
Joel Galensonf9c300d2021-09-22 14:30:25 -07001078 let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
1079 assert!(!extra.is_all());
1080 assert!(!(Flags::A | extra).is_all());
1081 assert!((Flags::ABC | extra).is_all());
1082
Jason Macnakefaa0952019-12-12 22:33:33 +00001083 assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all());
Joel Galensonf9c300d2021-09-22 14:30:25 -07001084
1085 assert!(EmptyFlags::all().is_all());
1086 assert!(EmptyFlags::empty().is_all());
Jason Macnakefaa0952019-12-12 22:33:33 +00001087 }
1088
1089 #[test]
1090 fn test_two_empties_do_not_intersect() {
1091 let e1 = Flags::empty();
1092 let e2 = Flags::empty();
1093 assert!(!e1.intersects(e2));
1094
1095 assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG));
1096 }
1097
1098 #[test]
1099 fn test_empty_does_not_intersect_with_full() {
1100 let e1 = Flags::empty();
1101 let e2 = Flags::ABC;
1102 assert!(!e1.intersects(e2));
1103 }
1104
1105 #[test]
1106 fn test_disjoint_intersects() {
1107 let e1 = Flags::A;
1108 let e2 = Flags::B;
1109 assert!(!e1.intersects(e2));
1110 }
1111
1112 #[test]
1113 fn test_overlapping_intersects() {
1114 let e1 = Flags::A;
1115 let e2 = Flags::A | Flags::B;
1116 assert!(e1.intersects(e2));
1117 }
1118
1119 #[test]
1120 fn test_contains() {
1121 let e1 = Flags::A;
1122 let e2 = Flags::A | Flags::B;
1123 assert!(!e1.contains(e2));
1124 assert!(e2.contains(e1));
1125 assert!(Flags::ABC.contains(e2));
1126
1127 assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG));
Joel Galensonf9c300d2021-09-22 14:30:25 -07001128
1129 assert!(EmptyFlags::empty().contains(EmptyFlags::empty()));
Jason Macnakefaa0952019-12-12 22:33:33 +00001130 }
1131
1132 #[test]
1133 fn test_insert() {
1134 let mut e1 = Flags::A;
1135 let e2 = Flags::A | Flags::B;
1136 e1.insert(e2);
1137 assert_eq!(e1, e2);
1138
1139 let mut e3 = AnotherSetOfFlags::empty();
1140 e3.insert(AnotherSetOfFlags::ANOTHER_FLAG);
1141 assert_eq!(e3, AnotherSetOfFlags::ANOTHER_FLAG);
1142 }
1143
1144 #[test]
1145 fn test_remove() {
1146 let mut e1 = Flags::A | Flags::B;
1147 let e2 = Flags::A | Flags::C;
1148 e1.remove(e2);
1149 assert_eq!(e1, Flags::B);
1150
1151 let mut e3 = AnotherSetOfFlags::ANOTHER_FLAG;
1152 e3.remove(AnotherSetOfFlags::ANOTHER_FLAG);
1153 assert_eq!(e3, AnotherSetOfFlags::empty());
1154 }
1155
1156 #[test]
1157 fn test_operators() {
1158 let e1 = Flags::A | Flags::C;
1159 let e2 = Flags::B | Flags::C;
1160 assert_eq!((e1 | e2), Flags::ABC); // union
1161 assert_eq!((e1 & e2), Flags::C); // intersection
1162 assert_eq!((e1 - e2), Flags::A); // set difference
1163 assert_eq!(!e2, Flags::A); // set complement
1164 assert_eq!(e1 ^ e2, Flags::A | Flags::B); // toggle
1165 let mut e3 = e1;
1166 e3.toggle(e2);
1167 assert_eq!(e3, Flags::A | Flags::B);
1168
1169 let mut m4 = AnotherSetOfFlags::empty();
1170 m4.toggle(AnotherSetOfFlags::empty());
1171 assert_eq!(m4, AnotherSetOfFlags::empty());
1172 }
1173
1174 #[test]
1175 fn test_operators_unchecked() {
1176 let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
1177 let e1 = Flags::A | Flags::C | extra;
1178 let e2 = Flags::B | Flags::C;
1179 assert_eq!((e1 | e2), (Flags::ABC | extra)); // union
1180 assert_eq!((e1 & e2), Flags::C); // intersection
1181 assert_eq!((e1 - e2), (Flags::A | extra)); // set difference
1182 assert_eq!(!e2, Flags::A); // set complement
1183 assert_eq!(!e1, Flags::B); // set complement
1184 assert_eq!(e1 ^ e2, Flags::A | Flags::B | extra); // toggle
1185 let mut e3 = e1;
1186 e3.toggle(e2);
1187 assert_eq!(e3, Flags::A | Flags::B | extra);
1188 }
1189
1190 #[test]
Joel Galensonf9c300d2021-09-22 14:30:25 -07001191 fn test_set_ops_basic() {
1192 let ab = Flags::A.union(Flags::B);
1193 let ac = Flags::A.union(Flags::C);
1194 let bc = Flags::B.union(Flags::C);
1195 assert_eq!(ab.bits, 0b011);
1196 assert_eq!(bc.bits, 0b110);
1197 assert_eq!(ac.bits, 0b101);
1198
1199 assert_eq!(ab, Flags::B.union(Flags::A));
1200 assert_eq!(ac, Flags::C.union(Flags::A));
1201 assert_eq!(bc, Flags::C.union(Flags::B));
1202
1203 assert_eq!(ac, Flags::A | Flags::C);
1204 assert_eq!(bc, Flags::B | Flags::C);
1205 assert_eq!(ab.union(bc), Flags::ABC);
1206
1207 assert_eq!(ac, Flags::A | Flags::C);
1208 assert_eq!(bc, Flags::B | Flags::C);
1209
1210 assert_eq!(ac.union(bc), ac | bc);
1211 assert_eq!(ac.union(bc), Flags::ABC);
1212 assert_eq!(bc.union(ac), Flags::ABC);
1213
1214 assert_eq!(ac.intersection(bc), ac & bc);
1215 assert_eq!(ac.intersection(bc), Flags::C);
1216 assert_eq!(bc.intersection(ac), Flags::C);
1217
1218 assert_eq!(ac.difference(bc), ac - bc);
1219 assert_eq!(bc.difference(ac), bc - ac);
1220 assert_eq!(ac.difference(bc), Flags::A);
1221 assert_eq!(bc.difference(ac), Flags::B);
1222
1223 assert_eq!(bc.complement(), !bc);
1224 assert_eq!(bc.complement(), Flags::A);
1225 assert_eq!(ac.symmetric_difference(bc), Flags::A.union(Flags::B));
1226 assert_eq!(bc.symmetric_difference(ac), Flags::A.union(Flags::B));
1227 }
1228
1229 #[test]
1230 fn test_set_ops_const() {
1231 // These just test that these compile and don't cause use-site panics
1232 // (would be possible if we had some sort of UB)
1233 const INTERSECT: Flags = Flags::all().intersection(Flags::C);
1234 const UNION: Flags = Flags::A.union(Flags::C);
1235 const DIFFERENCE: Flags = Flags::all().difference(Flags::A);
1236 const COMPLEMENT: Flags = Flags::C.complement();
1237 const SYM_DIFFERENCE: Flags = UNION.symmetric_difference(DIFFERENCE);
1238 assert_eq!(INTERSECT, Flags::C);
1239 assert_eq!(UNION, Flags::A | Flags::C);
1240 assert_eq!(DIFFERENCE, Flags::all() - Flags::A);
1241 assert_eq!(COMPLEMENT, !Flags::C);
1242 assert_eq!(SYM_DIFFERENCE, (Flags::A | Flags::C) ^ (Flags::all() - Flags::A));
1243 }
1244
1245 #[test]
1246 fn test_set_ops_unchecked() {
1247 let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
1248 let e1 = Flags::A.union(Flags::C).union(extra);
1249 let e2 = Flags::B.union(Flags::C);
1250 assert_eq!(e1.bits, 0b1101);
1251 assert_eq!(e1.union(e2), (Flags::ABC | extra));
1252 assert_eq!(e1.intersection(e2), Flags::C);
1253 assert_eq!(e1.difference(e2), Flags::A | extra);
1254 assert_eq!(e2.difference(e1), Flags::B);
1255 assert_eq!(e2.complement(), Flags::A);
1256 assert_eq!(e1.complement(), Flags::B);
1257 assert_eq!(e1.symmetric_difference(e2), Flags::A | Flags::B | extra); // toggle
1258 }
1259
1260 #[test]
1261 fn test_set_ops_exhaustive() {
1262 // Define a flag that contains gaps to help exercise edge-cases,
1263 // especially around "unknown" flags (e.g. ones outside of `all()`
1264 // `from_bits_unchecked`).
1265 // - when lhs and rhs both have different sets of unknown flags.
1266 // - unknown flags at both ends, and in the middle
1267 // - cases with "gaps".
1268 bitflags! {
1269 struct Test: u16 {
1270 // Intentionally no `A`
1271 const B = 0b000000010;
1272 // Intentionally no `C`
1273 const D = 0b000001000;
1274 const E = 0b000010000;
1275 const F = 0b000100000;
1276 const G = 0b001000000;
1277 // Intentionally no `H`
1278 const I = 0b100000000;
1279 }
1280 }
1281 let iter_test_flags =
1282 || (0..=0b111_1111_1111).map(|bits| unsafe { Test::from_bits_unchecked(bits) });
1283
1284 for a in iter_test_flags() {
1285 assert_eq!(
1286 a.complement(),
1287 Test::from_bits_truncate(!a.bits),
1288 "wrong result: !({:?})",
1289 a,
1290 );
1291 assert_eq!(a.complement(), !a, "named != op: !({:?})", a);
1292 for b in iter_test_flags() {
1293 // Check that the named operations produce the expected bitwise
1294 // values.
1295 assert_eq!(
1296 a.union(b).bits,
1297 a.bits | b.bits,
1298 "wrong result: `{:?}` | `{:?}`",
1299 a,
1300 b,
1301 );
1302 assert_eq!(
1303 a.intersection(b).bits,
1304 a.bits & b.bits,
1305 "wrong result: `{:?}` & `{:?}`",
1306 a,
1307 b,
1308 );
1309 assert_eq!(
1310 a.symmetric_difference(b).bits,
1311 a.bits ^ b.bits,
1312 "wrong result: `{:?}` ^ `{:?}`",
1313 a,
1314 b,
1315 );
1316 assert_eq!(
1317 a.difference(b).bits,
1318 a.bits & !b.bits,
1319 "wrong result: `{:?}` - `{:?}`",
1320 a,
1321 b,
1322 );
1323 // Note: Difference is checked as both `a - b` and `b - a`
1324 assert_eq!(
1325 b.difference(a).bits,
1326 b.bits & !a.bits,
1327 "wrong result: `{:?}` - `{:?}`",
1328 b,
1329 a,
1330 );
1331 // Check that the named set operations are equivalent to the
1332 // bitwise equivalents
1333 assert_eq!(a.union(b), a | b, "named != op: `{:?}` | `{:?}`", a, b,);
1334 assert_eq!(
1335 a.intersection(b),
1336 a & b,
1337 "named != op: `{:?}` & `{:?}`",
1338 a,
1339 b,
1340 );
1341 assert_eq!(
1342 a.symmetric_difference(b),
1343 a ^ b,
1344 "named != op: `{:?}` ^ `{:?}`",
1345 a,
1346 b,
1347 );
1348 assert_eq!(a.difference(b), a - b, "named != op: `{:?}` - `{:?}`", a, b,);
1349 // Note: Difference is checked as both `a - b` and `b - a`
1350 assert_eq!(b.difference(a), b - a, "named != op: `{:?}` - `{:?}`", b, a,);
1351 // Verify that the operations which should be symmetric are
1352 // actually symmetric.
1353 assert_eq!(a.union(b), b.union(a), "asymmetry: `{:?}` | `{:?}`", a, b,);
1354 assert_eq!(
1355 a.intersection(b),
1356 b.intersection(a),
1357 "asymmetry: `{:?}` & `{:?}`",
1358 a,
1359 b,
1360 );
1361 assert_eq!(
1362 a.symmetric_difference(b),
1363 b.symmetric_difference(a),
1364 "asymmetry: `{:?}` ^ `{:?}`",
1365 a,
1366 b,
1367 );
1368 }
1369 }
1370 }
1371
1372 #[test]
Jason Macnakefaa0952019-12-12 22:33:33 +00001373 fn test_set() {
1374 let mut e1 = Flags::A | Flags::C;
1375 e1.set(Flags::B, true);
1376 e1.set(Flags::C, false);
1377
1378 assert_eq!(e1, Flags::A | Flags::B);
1379 }
1380
1381 #[test]
1382 fn test_assignment_operators() {
1383 let mut m1 = Flags::empty();
1384 let e1 = Flags::A | Flags::C;
1385 // union
1386 m1 |= Flags::A;
1387 assert_eq!(m1, Flags::A);
1388 // intersection
1389 m1 &= e1;
1390 assert_eq!(m1, Flags::A);
1391 // set difference
1392 m1 -= m1;
1393 assert_eq!(m1, Flags::empty());
1394 // toggle
1395 m1 ^= e1;
1396 assert_eq!(m1, e1);
1397 }
1398
Jason Macnakefaa0952019-12-12 22:33:33 +00001399 #[test]
1400 fn test_const_fn() {
1401 const _M1: Flags = Flags::empty();
1402
1403 const M2: Flags = Flags::A;
1404 assert_eq!(M2, Flags::A);
1405
1406 const M3: Flags = Flags::C;
1407 assert_eq!(M3, Flags::C);
1408 }
1409
1410 #[test]
1411 fn test_extend() {
1412 let mut flags;
1413
1414 flags = Flags::empty();
1415 flags.extend([].iter().cloned());
1416 assert_eq!(flags, Flags::empty());
1417
1418 flags = Flags::empty();
1419 flags.extend([Flags::A, Flags::B].iter().cloned());
1420 assert_eq!(flags, Flags::A | Flags::B);
1421
1422 flags = Flags::A;
1423 flags.extend([Flags::A, Flags::B].iter().cloned());
1424 assert_eq!(flags, Flags::A | Flags::B);
1425
1426 flags = Flags::B;
1427 flags.extend([Flags::A, Flags::ABC].iter().cloned());
1428 assert_eq!(flags, Flags::ABC);
1429 }
1430
1431 #[test]
1432 fn test_from_iterator() {
1433 assert_eq!([].iter().cloned().collect::<Flags>(), Flags::empty());
1434 assert_eq!(
1435 [Flags::A, Flags::B].iter().cloned().collect::<Flags>(),
1436 Flags::A | Flags::B
1437 );
1438 assert_eq!(
1439 [Flags::A, Flags::ABC].iter().cloned().collect::<Flags>(),
1440 Flags::ABC
1441 );
1442 }
1443
1444 #[test]
1445 fn test_lt() {
1446 let mut a = Flags::empty();
1447 let mut b = Flags::empty();
1448
1449 assert!(!(a < b) && !(b < a));
1450 b = Flags::B;
1451 assert!(a < b);
1452 a = Flags::C;
1453 assert!(!(a < b) && b < a);
1454 b = Flags::C | Flags::B;
1455 assert!(a < b);
1456 }
1457
1458 #[test]
1459 fn test_ord() {
1460 let mut a = Flags::empty();
1461 let mut b = Flags::empty();
1462
1463 assert!(a <= b && a >= b);
1464 a = Flags::A;
1465 assert!(a > b && a >= b);
1466 assert!(b < a && b <= a);
1467 b = Flags::B;
1468 assert!(b > a && b >= a);
1469 assert!(a < b && a <= b);
1470 }
1471
1472 fn hash<T: Hash>(t: &T) -> u64 {
1473 let mut s = DefaultHasher::new();
1474 t.hash(&mut s);
1475 s.finish()
1476 }
1477
1478 #[test]
1479 fn test_hash() {
1480 let mut x = Flags::empty();
1481 let mut y = Flags::empty();
1482 assert_eq!(hash(&x), hash(&y));
1483 x = Flags::all();
1484 y = Flags::ABC;
1485 assert_eq!(hash(&x), hash(&y));
1486 }
1487
1488 #[test]
Joel Galensonf9c300d2021-09-22 14:30:25 -07001489 fn test_default() {
1490 assert_eq!(Flags::empty(), Flags::default());
1491 }
1492
1493 #[test]
Jason Macnakefaa0952019-12-12 22:33:33 +00001494 fn test_debug() {
1495 assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
1496 assert_eq!(format!("{:?}", Flags::empty()), "(empty)");
1497 assert_eq!(format!("{:?}", Flags::ABC), "A | B | C | ABC");
1498 let extra = unsafe { Flags::from_bits_unchecked(0xb8) };
1499 assert_eq!(format!("{:?}", extra), "0xb8");
1500 assert_eq!(format!("{:?}", Flags::A | extra), "A | 0xb8");
Joel Galensonf9c300d2021-09-22 14:30:25 -07001501
1502 assert_eq!(
1503 format!("{:?}", Flags::ABC | extra),
1504 "A | B | C | ABC | 0xb8"
1505 );
1506
1507 assert_eq!(format!("{:?}", EmptyFlags::empty()), "(empty)");
Jason Macnakefaa0952019-12-12 22:33:33 +00001508 }
1509
1510 #[test]
1511 fn test_binary() {
1512 assert_eq!(format!("{:b}", Flags::ABC), "111");
1513 assert_eq!(format!("{:#b}", Flags::ABC), "0b111");
1514 let extra = unsafe { Flags::from_bits_unchecked(0b1010000) };
1515 assert_eq!(format!("{:b}", Flags::ABC | extra), "1010111");
1516 assert_eq!(format!("{:#b}", Flags::ABC | extra), "0b1010111");
1517 }
1518
1519 #[test]
1520 fn test_octal() {
1521 assert_eq!(format!("{:o}", LongFlags::LONG_A), "177777");
1522 assert_eq!(format!("{:#o}", LongFlags::LONG_A), "0o177777");
1523 let extra = unsafe { LongFlags::from_bits_unchecked(0o5000000) };
1524 assert_eq!(format!("{:o}", LongFlags::LONG_A | extra), "5177777");
1525 assert_eq!(format!("{:#o}", LongFlags::LONG_A | extra), "0o5177777");
1526 }
1527
1528 #[test]
1529 fn test_lowerhex() {
1530 assert_eq!(format!("{:x}", LongFlags::LONG_A), "ffff");
1531 assert_eq!(format!("{:#x}", LongFlags::LONG_A), "0xffff");
1532 let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) };
1533 assert_eq!(format!("{:x}", LongFlags::LONG_A | extra), "e0ffff");
1534 assert_eq!(format!("{:#x}", LongFlags::LONG_A | extra), "0xe0ffff");
1535 }
1536
1537 #[test]
1538 fn test_upperhex() {
1539 assert_eq!(format!("{:X}", LongFlags::LONG_A), "FFFF");
1540 assert_eq!(format!("{:#X}", LongFlags::LONG_A), "0xFFFF");
1541 let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) };
1542 assert_eq!(format!("{:X}", LongFlags::LONG_A | extra), "E0FFFF");
1543 assert_eq!(format!("{:#X}", LongFlags::LONG_A | extra), "0xE0FFFF");
1544 }
1545
1546 mod submodule {
1547 bitflags! {
1548 pub struct PublicFlags: i8 {
1549 const X = 0;
1550 }
Joel Galensonf9c300d2021-09-22 14:30:25 -07001551
Jason Macnakefaa0952019-12-12 22:33:33 +00001552 struct PrivateFlags: i8 {
1553 const Y = 0;
1554 }
1555 }
1556
1557 #[test]
1558 fn test_private() {
1559 let _ = PrivateFlags::Y;
1560 }
1561 }
1562
1563 #[test]
1564 fn test_public() {
1565 let _ = submodule::PublicFlags::X;
1566 }
1567
1568 mod t1 {
1569 mod foo {
1570 pub type Bar = i32;
1571 }
1572
1573 bitflags! {
1574 /// baz
1575 struct Flags: foo::Bar {
1576 const A = 0b00000001;
1577 #[cfg(foo)]
1578 const B = 0b00000010;
1579 #[cfg(foo)]
1580 const C = 0b00000010;
1581 }
1582 }
1583 }
1584
1585 #[test]
1586 fn test_in_function() {
1587 bitflags! {
1588 struct Flags: u8 {
1589 const A = 1;
1590 #[cfg(any())] // false
1591 const B = 2;
1592 }
1593 }
1594 assert_eq!(Flags::all(), Flags::A);
1595 assert_eq!(format!("{:?}", Flags::A), "A");
1596 }
1597
1598 #[test]
1599 fn test_deprecated() {
1600 bitflags! {
1601 pub struct TestFlags: u32 {
1602 #[deprecated(note = "Use something else.")]
1603 const ONE = 1;
1604 }
1605 }
1606 }
1607
1608 #[test]
1609 fn test_pub_crate() {
1610 mod module {
1611 bitflags! {
1612 pub (crate) struct Test: u8 {
1613 const FOO = 1;
1614 }
1615 }
1616 }
1617
1618 assert_eq!(module::Test::FOO.bits(), 1);
1619 }
1620
1621 #[test]
1622 fn test_pub_in_module() {
1623 mod module {
1624 mod submodule {
1625 bitflags! {
1626 // `pub (in super)` means only the module `module` will
1627 // be able to access this.
1628 pub (in super) struct Test: u8 {
1629 const FOO = 1;
1630 }
1631 }
1632 }
1633
1634 mod test {
1635 // Note: due to `pub (in super)`,
1636 // this cannot be accessed directly by the testing code.
1637 pub(super) fn value() -> u8 {
1638 super::submodule::Test::FOO.bits()
1639 }
1640 }
1641
1642 pub fn value() -> u8 {
1643 test::value()
1644 }
1645 }
1646
1647 assert_eq!(module::value(), 1)
1648 }
1649
1650 #[test]
1651 fn test_zero_value_flags() {
1652 bitflags! {
1653 struct Flags: u32 {
1654 const NONE = 0b0;
1655 const SOME = 0b1;
1656 }
1657 }
1658
1659 assert!(Flags::empty().contains(Flags::NONE));
1660 assert!(Flags::SOME.contains(Flags::NONE));
1661 assert!(Flags::NONE.is_empty());
1662
1663 assert_eq!(format!("{:?}", Flags::empty()), "NONE");
1664 assert_eq!(format!("{:?}", Flags::SOME), "SOME");
1665 }
Joel Galensonf9c300d2021-09-22 14:30:25 -07001666
1667 #[test]
1668 fn test_empty_bitflags() {
1669 bitflags! {}
1670 }
1671
1672 #[test]
1673 fn test_u128_bitflags() {
1674 bitflags! {
1675 struct Flags128: u128 {
1676 const A = 0x0000_0000_0000_0000_0000_0000_0000_0001;
1677 const B = 0x0000_0000_0000_1000_0000_0000_0000_0000;
1678 const C = 0x8000_0000_0000_0000_0000_0000_0000_0000;
1679 const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
1680 }
1681 }
1682
1683 assert_eq!(Flags128::ABC, Flags128::A | Flags128::B | Flags128::C);
1684 assert_eq!(Flags128::A.bits, 0x0000_0000_0000_0000_0000_0000_0000_0001);
1685 assert_eq!(Flags128::B.bits, 0x0000_0000_0000_1000_0000_0000_0000_0000);
1686 assert_eq!(Flags128::C.bits, 0x8000_0000_0000_0000_0000_0000_0000_0000);
1687 assert_eq!(
1688 Flags128::ABC.bits,
1689 0x8000_0000_0000_1000_0000_0000_0000_0001
1690 );
1691 assert_eq!(format!("{:?}", Flags128::A), "A");
1692 assert_eq!(format!("{:?}", Flags128::B), "B");
1693 assert_eq!(format!("{:?}", Flags128::C), "C");
1694 assert_eq!(format!("{:?}", Flags128::ABC), "A | B | C | ABC");
1695 }
1696
1697 #[test]
1698 fn test_serde_bitflags_serialize() {
1699 let flags = SerdeFlags::A | SerdeFlags::B;
1700
1701 let serialized = serde_json::to_string(&flags).unwrap();
1702
1703 assert_eq!(serialized, r#"{"bits":3}"#);
1704 }
1705
1706 #[test]
1707 fn test_serde_bitflags_deserialize() {
1708 let deserialized: SerdeFlags = serde_json::from_str(r#"{"bits":12}"#).unwrap();
1709
1710 let expected = SerdeFlags::C | SerdeFlags::D;
1711
1712 assert_eq!(deserialized.bits, expected.bits);
1713 }
1714
1715 #[test]
1716 fn test_serde_bitflags_roundtrip() {
1717 let flags = SerdeFlags::A | SerdeFlags::B;
1718
1719 let deserialized: SerdeFlags = serde_json::from_str(&serde_json::to_string(&flags).unwrap()).unwrap();
1720
1721 assert_eq!(deserialized.bits, flags.bits);
1722 }
1723
1724 bitflags! {
1725 #[derive(serde::Serialize, serde::Deserialize)]
1726 struct SerdeFlags: u32 {
1727 const A = 1;
1728 const B = 2;
1729 const C = 4;
1730 const D = 8;
1731 }
1732 }
Jason Macnakefaa0952019-12-12 22:33:33 +00001733}