diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/bitflags/src/lib.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/bitflags/src/lib.rs')
-rw-r--r-- | vendor/bitflags/src/lib.rs | 1435 |
1 files changed, 698 insertions, 737 deletions
diff --git a/vendor/bitflags/src/lib.rs b/vendor/bitflags/src/lib.rs index 935e432f1..d28fd87f7 100644 --- a/vendor/bitflags/src/lib.rs +++ b/vendor/bitflags/src/lib.rs @@ -8,24 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A typesafe bitmask flag generator useful for sets of C-style bitmask flags. -//! It can be used for creating typesafe wrappers around C APIs. +//! A typesafe bitmask flag generator useful for sets of C-style flags. +//! It can be used for creating ergonomic wrappers around C APIs. //! //! The `bitflags!` macro generates `struct`s that manage a set of flags. The -//! flags should only be defined for integer types, otherwise unexpected type -//! errors may occur at compile time. +//! type of those flags must be some primitive integer. //! -//! # Example +//! # Examples //! //! ``` //! use bitflags::bitflags; //! //! bitflags! { +//! #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] //! struct Flags: u32 { //! const A = 0b00000001; //! const B = 0b00000010; //! const C = 0b00000100; -//! const ABC = Self::A.bits | Self::B.bits | Self::C.bits; +//! const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits(); //! } //! } //! @@ -42,59 +42,22 @@ //! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code //! generated by the above `bitflags!` expansion. //! -//! The generated `struct`s can also be extended with type and trait -//! implementations: -//! -//! ``` -//! use std::fmt; -//! -//! use bitflags::bitflags; -//! -//! bitflags! { -//! struct Flags: u32 { -//! const A = 0b00000001; -//! const B = 0b00000010; -//! } -//! } -//! -//! impl Flags { -//! pub fn clear(&mut self) { -//! self.bits = 0; // The `bits` field can be accessed from within the -//! // same module where the `bitflags!` macro was invoked. -//! } -//! } -//! -//! impl fmt::Display for Flags { -//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -//! write!(f, "hi!") -//! } -//! } -//! -//! fn main() { -//! let mut flags = Flags::A | Flags::B; -//! flags.clear(); -//! assert!(flags.is_empty()); -//! assert_eq!(format!("{}", flags), "hi!"); -//! assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); -//! assert_eq!(format!("{:?}", Flags::B), "B"); -//! } -//! ``` -//! //! # Visibility //! -//! The generated structs and their associated flag constants are not exported -//! out of the current module by default. A definition can be exported out of -//! the current module by adding `pub` before `struct`: +//! The `bitflags!` macro supports visibility, just like you'd expect when writing a normal +//! Rust `struct`: //! //! ``` //! mod example { //! use bitflags::bitflags; //! //! bitflags! { +//! #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] //! pub struct Flags1: u32 { //! const A = 0b00000001; //! } //! +//! #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] //! # pub //! struct Flags2: u32 { //! const B = 0b00000010; @@ -110,19 +73,22 @@ //! //! # Attributes //! -//! Attributes can be attached to the generated `struct`s by placing them -//! before the `struct` keyword. +//! Attributes can be attached to the generated flags types and their constants as normal. //! -//! ## Representations +//! # Representation //! -//! It's valid to add a `#[repr(C)]` or `#[repr(transparent)]` attribute to a type -//! generated by `bitflags!`. In these cases, the type is guaranteed to be a newtype. +//! It's valid to add a `#[repr(C)]` or `#[repr(transparent)]` attribute to a generated flags type. +//! The generated flags type is always guaranteed to be a newtype where its only field has the same +//! ABI as the underlying integer type. +//! +//! In this example, `Flags` has the same ABI as `u32`: //! //! ``` //! use bitflags::bitflags; //! //! bitflags! { //! #[repr(transparent)] +//! #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] //! struct Flags: u32 { //! const A = 0b00000001; //! const B = 0b00000010; @@ -131,19 +97,65 @@ //! } //! ``` //! -//! # Trait implementations +//! # Extending +//! +//! Generated flags types belong to you, so you can add trait implementations to them outside +//! of what the `bitflags!` macro gives: +//! +//! ``` +//! use std::fmt; +//! +//! use bitflags::bitflags; +//! +//! bitflags! { +//! #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +//! struct Flags: u32 { +//! const A = 0b00000001; +//! const B = 0b00000010; +//! } +//! } +//! +//! impl Flags { +//! pub fn clear(&mut self) { +//! *self.0.bits_mut() = 0; +//! } +//! } +//! +//! fn main() { +//! let mut flags = Flags::A | Flags::B; //! -//! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` -//! traits are automatically derived for the `struct`s using the `derive` attribute. -//! Additional traits can be derived by providing an explicit `derive` -//! attribute on `struct`. +//! flags.clear(); +//! assert!(flags.is_empty()); //! -//! The `Extend` and `FromIterator` traits are implemented for the `struct`s, -//! too: `Extend` adds the union of the instances of the `struct` iterated over, -//! while `FromIterator` calculates the union. +//! assert_eq!(format!("{:?}", Flags::A | Flags::B), "Flags(A | B)"); +//! assert_eq!(format!("{:?}", Flags::B), "Flags(B)"); +//! } +//! ``` //! -//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` traits are also -//! implemented by displaying the bits value of the internal struct. +//! # What's implemented by `bitflags!` +//! +//! The `bitflags!` macro adds some trait implementations and inherent methods +//! to generated flags types, but leaves room for you to choose the semantics +//! of others. +//! +//! ## Iterators +//! +//! The following iterator traits are implemented for generated flags types: +//! +//! - `Extend`: adds the union of the instances iterated over. +//! - `FromIterator`: calculates the union. +//! - `IntoIterator`: iterates over set flag values. +//! +//! ## Formatting +//! +//! The following formatting traits are implemented for generated flags types: +//! +//! - `Binary`. +//! - `LowerHex` and `UpperHex`. +//! - `Octal`. +//! +//! Also see the _Debug and Display_ section for details about standard text +//! representations for flags types. //! //! ## Operators //! @@ -155,7 +167,7 @@ //! - `Sub` and `SubAssign`: set difference //! - `Not`: set complement //! -//! # Methods +//! ## Methods //! //! The following methods are defined for the generated `struct`s: //! @@ -167,7 +179,7 @@ //! defined flag //! - `from_bits_truncate`: convert from underlying bit representation, dropping //! any bits that do not correspond to defined flags -//! - `from_bits_unchecked`: convert from underlying bit representation, keeping +//! - `from_bits_retain`: convert from underlying bit representation, keeping //! all bits (even those not corresponding to defined //! flags) //! - `is_empty`: `true` if no flags are currently stored @@ -192,7 +204,18 @@ //! - `complement`: returns a new set of flags, containing all flags which are //! not set in `self`, but which are allowed for this type. //! -//! ## Default +//! # What's not implemented by `bitflags!` +//! +//! Some functionality is not automatically implemented for generated flags types +//! by the `bitflags!` macro, even when it reasonably could be. This is so callers +//! have more freedom to decide on the semantics of their flags types. +//! +//! ## `Clone` and `Copy` +//! +//! Generated flags types are not automatically copyable, even though they can always +//! derive both `Clone` and `Copy`. +//! +//! ## `Default` //! //! The `Default` trait is not automatically implemented for the generated structs. //! @@ -204,7 +227,7 @@ //! //! bitflags! { //! // Results in default value with bits: 0 -//! #[derive(Default)] +//! #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)] //! struct Flags: u32 { //! const A = 0b00000001; //! const B = 0b00000010; @@ -224,6 +247,7 @@ //! use bitflags::bitflags; //! //! bitflags! { +//! #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] //! struct Flags: u32 { //! const A = 0b00000001; //! const B = 0b00000010; @@ -244,7 +268,57 @@ //! } //! ``` //! -//! # Zero Flags +//! ## `Debug` and `Display` +//! +//! The `Debug` trait can be derived for a reasonable implementation. This library defines a standard +//! text-based representation for flags that generated flags types can use. For details on the exact +//! grammar, see the [`parser`] module. +//! +//! To support formatting and parsing your generated flags types using that representation, you can implement +//! the standard `Display` and `FromStr` traits in this fashion: +//! +//! ``` +//! use bitflags::bitflags; +//! use std::{fmt, str}; +//! +//! bitflags::bitflags! { +//! pub struct Flags: u32 { +//! const A = 1; +//! const B = 2; +//! const C = 4; +//! const D = 8; +//! } +//! } +//! +//! impl fmt::Debug for Flags { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! fmt::Debug::fmt(&self.0, f) +//! } +//! } +//! +//! impl fmt::Display for Flags { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! fmt::Display::fmt(&self.0, f) +//! } +//! } +//! +//! impl str::FromStr for Flags { +//! type Err = bitflags::parser::ParseError; +//! +//! fn from_str(flags: &str) -> Result<Self, Self::Err> { +//! Ok(Self(flags.parse()?)) +//! } +//! } +//! ``` +//! +//! ## `PartialEq` and `PartialOrd` +//! +//! Equality and ordering can be derived for a reasonable implementation, or implemented manually +//! for different semantics. +//! +//! # Edge cases +//! +//! ## Zero Flags //! //! Flags with a value equal to zero will have some strange behavior that one should be aware of. //! @@ -252,6 +326,7 @@ //! use bitflags::bitflags; //! //! bitflags! { +//! #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] //! struct Flags: u32 { //! const NONE = 0b00000000; //! const SOME = 0b00000001; @@ -274,14 +349,147 @@ //! ``` //! //! Users should generally avoid defining a flag with a value of zero. +//! +//! ## Multi-bit Flags +//! +//! It is allowed to define a flag with multiple bits set, however such +//! flags are _not_ treated as a set where any of those bits is a valid +//! flag. Instead, each flag is treated as a unit when converting from +//! bits with [`from_bits`] or [`from_bits_truncate`]. +//! +//! ``` +//! use bitflags::bitflags; +//! +//! bitflags! { +//! #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +//! struct Flags: u8 { +//! const F3 = 0b00000011; +//! } +//! } +//! +//! fn main() { +//! // This bit pattern does not set all the bits in `F3`, so it is rejected. +//! assert!(Flags::from_bits(0b00000001).is_none()); +//! assert!(Flags::from_bits_truncate(0b00000001).is_empty()); +//! } +//! ``` +//! +//! [`from_bits`]: BitFlags::from_bits +//! [`from_bits_truncate`]: BitFlags::from_bits_truncate +//! +//! # The `BitFlags` trait +//! +//! This library defines a `BitFlags` trait that's implemented by all generated flags types. +//! The trait makes it possible to work with flags types generically: +//! +//! ``` +//! fn count_unset_flags<F: bitflags::BitFlags>(flags: &F) -> usize { +//! // Find out how many flags there are in total +//! let total = F::all().iter().count(); +//! +//! // Find out how many flags are set +//! let set = flags.iter().count(); +//! +//! total - set +//! } +//! +//! use bitflags::bitflags; +//! +//! bitflags! { +//! #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +//! struct Flags: u32 { +//! const A = 0b00000001; +//! const B = 0b00000010; +//! const C = 0b00000100; +//! } +//! } +//! +//! assert_eq!(2, count_unset_flags(&Flags::B)); +//! ``` +//! +//! # The internal field +//! +//! This library generates newtypes like: +//! +//! ``` +//! # pub struct Field0; +//! pub struct Flags(Field0); +//! ``` +//! +//! You can freely use methods and trait implementations on this internal field as `.0`. +//! For details on exactly what's generated for it, see the [`Field0`](example_generated/struct.Field0.html) +//! example docs. + +#![cfg_attr(not(any(feature = "std", test)), no_std)] +#![cfg_attr(not(test), forbid(unsafe_code))] + +#![doc(html_root_url = "https://docs.rs/bitflags/2.2.1")] + +#[doc(inline)] +pub use traits::BitFlags; -#![cfg_attr(not(test), no_std)] -#![doc(html_root_url = "https://docs.rs/bitflags/1.3.2")] +pub mod parser; +mod traits; #[doc(hidden)] -pub extern crate core as _core; +pub mod __private { + pub use crate::{external::*, traits::*}; + + pub use core; +} + +/* +How does the bitflags crate work? -/// The macro used to generate the flag structures. +This library generates a `struct` in the end-user's crate with a bunch of constants on it that represent flags. +The difference between `bitflags` and a lot of other libraries is that we don't actually control the generated `struct` in the end. +It's part of the end-user's crate, so it belongs to them. That makes it difficult to extend `bitflags` with new functionality +because we could end up breaking valid code that was already written. + +Our solution is to split the type we generate into two: the public struct owned by the end-user, and an internal struct owned by `bitflags` (us). +To give you an example, let's say we had a crate that called `bitflags!`: + +```rust +bitflags! { + pub struct MyFlags: u32 { + const A = 1; + const B = 2; + } +} +``` + +What they'd end up with looks something like this: + +```rust +pub struct MyFlags(<MyFlags as PublicFlags>::InternalBitFlags); + +const _: () = { + #[repr(transparent)] + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct MyInternalBitFlags { + bits: u32, + } + + impl PublicFlags for MyFlags { + type Internal = InternalBitFlags; + } +}; +``` + +If we want to expose something like a new trait impl for generated flags types, we add it to our generated `MyInternalBitFlags`, +and let `#[derive]` on `MyFlags` pick up that implementation, if an end-user chooses to add one. + +The public API is generated in the `__impl_public_flags!` macro, and the internal API is generated in +the `__impl_internal_flags!` macro. + +The macros are split into 3 modules: + +- `public`: where the user-facing flags types are generated. +- `internal`: where the `bitflags`-facing flags types are generated. +- `external`: where external library traits are implemented conditionally. +*/ + +/// The macro used to generate the flag structure. /// /// See the [crate level docs](../bitflags/index.html) for complete documentation. /// @@ -291,22 +499,21 @@ pub extern crate core as _core; /// use bitflags::bitflags; /// /// bitflags! { +/// #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] /// struct Flags: u32 { /// const A = 0b00000001; /// const B = 0b00000010; /// const C = 0b00000100; -/// const ABC = Self::A.bits | Self::B.bits | Self::C.bits; +/// const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits(); /// } /// } /// -/// fn main() { -/// let e1 = Flags::A | Flags::C; -/// let e2 = Flags::B | Flags::C; -/// assert_eq!((e1 | e2), Flags::ABC); // union -/// assert_eq!((e1 & e2), Flags::C); // intersection -/// assert_eq!((e1 - e2), Flags::A); // set difference -/// assert_eq!(!e2, Flags::A); // set complement -/// } +/// let e1 = Flags::A | Flags::C; +/// let e2 = Flags::B | Flags::C; +/// assert_eq!((e1 | e2), Flags::ABC); // union +/// assert_eq!((e1 & e2), Flags::C); // intersection +/// assert_eq!((e1 - e2), Flags::A); // set difference +/// assert_eq!(!e2, Flags::A); // set complement /// ``` /// /// The generated `struct`s can also be extended with type and trait @@ -318,6 +525,7 @@ pub extern crate core as _core; /// use bitflags::bitflags; /// /// bitflags! { +/// #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] /// struct Flags: u32 { /// const A = 0b00000001; /// const B = 0b00000010; @@ -326,25 +534,17 @@ pub extern crate core as _core; /// /// impl Flags { /// pub fn clear(&mut self) { -/// self.bits = 0; // The `bits` field can be accessed from within the -/// // same module where the `bitflags!` macro was invoked. +/// *self.0.bits_mut() = 0; /// } /// } /// -/// impl fmt::Display for Flags { -/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -/// write!(f, "hi!") -/// } -/// } +/// let mut flags = Flags::A | Flags::B; /// -/// fn main() { -/// let mut flags = Flags::A | Flags::B; -/// flags.clear(); -/// assert!(flags.is_empty()); -/// assert_eq!(format!("{}", flags), "hi!"); -/// assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); -/// assert_eq!(format!("{:?}", Flags::B), "B"); -/// } +/// flags.clear(); +/// assert!(flags.is_empty()); +/// +/// assert_eq!(format!("{:?}", Flags::A | Flags::B), "Flags(A | B)"); +/// assert_eq!(format!("{:?}", Flags::B), "Flags(B)"); /// ``` #[macro_export(local_inner_macros)] macro_rules! bitflags { @@ -359,592 +559,103 @@ macro_rules! bitflags { $($t:tt)* ) => { - $(#[$outer])* - #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] - $vis struct $BitFlags { - bits: $T, + // Declared in the scope of the `bitflags!` call + // This type appears in the end-user's API + __declare_public_bitflags! { + $(#[$outer])* + $vis struct $BitFlags; } - __impl_bitflags! { - $BitFlags: $T { + // Workaround for: https://github.com/bitflags/bitflags/issues/320 + __impl_public_bitflags_consts! { + $BitFlags { $( $(#[$inner $($args)*])* + #[allow( + dead_code, + deprecated, + unused_attributes, + non_upper_case_globals + )] $Flag = $value; )* } } - bitflags! { - $($t)* - } - }; - () => {}; -} - -// A helper macro to implement the `all` function. -#[macro_export(local_inner_macros)] -#[doc(hidden)] -macro_rules! __impl_all_bitflags { - ( - $BitFlags:ident: $T:ty { - $( - $(#[$attr:ident $($args:tt)*])* - $Flag:ident = $value:expr; - )+ - } - ) => { - // See `Debug::fmt` for why this approach is taken. - #[allow(non_snake_case)] - trait __BitFlags { - $( - const $Flag: $T = 0; - )+ - } - #[allow(non_snake_case)] - impl __BitFlags for $BitFlags { - $( - __impl_bitflags! { - #[allow(deprecated)] - $(? #[$attr $($args)*])* - const $Flag: $T = Self::$Flag.bits; - } - )+ - } - Self { bits: $(<Self as __BitFlags>::$Flag)|+ } - }; - ( - $BitFlags:ident: $T:ty { } - ) => { - Self { bits: 0 } - }; -} + #[allow( + dead_code, + deprecated, + unused_doc_comments, + unused_attributes, + unused_mut, + unused_imports, + non_upper_case_globals + )] + const _: () = { + // Declared in a "hidden" scope that can't be reached directly + // These types don't appear in the end-user's API + __declare_internal_bitflags! { + $vis struct InternalBitFlags: $T; + $vis struct Iter; + $vis struct IterRaw; + } -#[macro_export(local_inner_macros)] -#[doc(hidden)] -macro_rules! __impl_bitflags { - ( - $BitFlags:ident: $T:ty { - $( - $(#[$attr:ident $($args:tt)*])* - $Flag:ident = $value:expr; - )* - } - ) => { - impl $crate::_core::fmt::Debug for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { - // This convoluted approach is to handle #[cfg]-based flag - // omission correctly. For example it needs to support: - // - // #[cfg(unix)] const A: Flag = /* ... */; - // #[cfg(windows)] const B: Flag = /* ... */; - - // Unconditionally define a check for every flag, even disabled - // ones. - #[allow(non_snake_case)] - trait __BitFlags { + __impl_internal_bitflags! { + InternalBitFlags: $T, $BitFlags, Iter, IterRaw { $( - #[inline] - fn $Flag(&self) -> bool { false } + $(#[$inner $($args)*])* + $Flag; )* } + } - // Conditionally override the check for just those flags that - // are not #[cfg]ed away. - #[allow(non_snake_case)] - impl __BitFlags for $BitFlags { + // This is where new library trait implementations can be added + __impl_external_bitflags! { + InternalBitFlags: $T { $( - __impl_bitflags! { - #[allow(deprecated)] - #[inline] - $(? #[$attr $($args)*])* - fn $Flag(&self) -> bool { - if Self::$Flag.bits == 0 && self.bits != 0 { - false - } else { - self.bits & Self::$Flag.bits == Self::$Flag.bits - } - } - } + $(#[$inner $($args)*])* + $Flag; )* } - - let mut first = true; - $( - if <Self as __BitFlags>::$Flag(self) { - if !first { - f.write_str(" | ")?; - } - first = false; - f.write_str($crate::_core::stringify!($Flag))?; - } - )* - let extra_bits = self.bits & !Self::all().bits(); - if extra_bits != 0 { - if !first { - f.write_str(" | ")?; - } - first = false; - f.write_str("0x")?; - $crate::_core::fmt::LowerHex::fmt(&extra_bits, f)?; - } - if first { - f.write_str("(empty)")?; - } - Ok(()) - } - } - impl $crate::_core::fmt::Binary for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { - $crate::_core::fmt::Binary::fmt(&self.bits, f) - } - } - impl $crate::_core::fmt::Octal for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { - $crate::_core::fmt::Octal::fmt(&self.bits, f) } - } - impl $crate::_core::fmt::LowerHex for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { - $crate::_core::fmt::LowerHex::fmt(&self.bits, f) - } - } - impl $crate::_core::fmt::UpperHex for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { - $crate::_core::fmt::UpperHex::fmt(&self.bits, f) - } - } - #[allow(dead_code)] - impl $BitFlags { - $( - $(#[$attr $($args)*])* - pub const $Flag: Self = Self { bits: $value }; - )* - - /// Returns an empty set of flags. - #[inline] - pub const fn empty() -> Self { - Self { bits: 0 } - } - - /// Returns the set containing all flags. - #[inline] - pub const fn all() -> Self { - __impl_all_bitflags! { - $BitFlags: $T { - $( - $(#[$attr $($args)*])* - $Flag = $value; - )* - } - } - } - - /// Returns the raw value of the flags currently stored. - #[inline] - pub const fn bits(&self) -> $T { - self.bits + __impl_public_bitflags! { + $BitFlags: $T, InternalBitFlags, Iter, IterRaw; } + }; - /// Convert from underlying bit representation, unless that - /// representation contains bits that do not correspond to a flag. - #[inline] - pub const fn from_bits(bits: $T) -> $crate::_core::option::Option<Self> { - if (bits & !Self::all().bits()) == 0 { - $crate::_core::option::Option::Some(Self { bits }) - } else { - $crate::_core::option::Option::None - } - } - - /// Convert from underlying bit representation, dropping any bits - /// that do not correspond to flags. - #[inline] - pub const fn from_bits_truncate(bits: $T) -> Self { - Self { bits: bits & Self::all().bits } - } - - /// Convert from underlying bit representation, preserving all - /// bits (even those not corresponding to a defined flag). - /// - /// # Safety - /// - /// The caller of the `bitflags!` macro can chose to allow or - /// disallow extra bits for their bitflags type. - /// - /// The caller of `from_bits_unchecked()` has to ensure that - /// all bits correspond to a defined flag or that extra bits - /// are valid for this bitflags type. - #[inline] - pub const unsafe fn from_bits_unchecked(bits: $T) -> Self { - Self { bits } - } - - /// Returns `true` if no flags are currently stored. - #[inline] - pub const fn is_empty(&self) -> bool { - self.bits() == Self::empty().bits() - } - - /// Returns `true` if all flags are currently set. - #[inline] - pub const fn is_all(&self) -> bool { - Self::all().bits | self.bits == self.bits - } - - /// Returns `true` if there are flags common to both `self` and `other`. - #[inline] - pub const fn intersects(&self, other: Self) -> bool { - !(Self { bits: self.bits & other.bits}).is_empty() - } - - /// Returns `true` if all of the flags in `other` are contained within `self`. - #[inline] - pub const fn contains(&self, other: Self) -> bool { - (self.bits & other.bits) == other.bits - } - - /// Inserts the specified flags in-place. - #[inline] - pub fn insert(&mut self, other: Self) { - self.bits |= other.bits; - } - - /// Removes the specified flags in-place. - #[inline] - pub fn remove(&mut self, other: Self) { - self.bits &= !other.bits; - } - - /// Toggles the specified flags in-place. - #[inline] - pub fn toggle(&mut self, other: Self) { - self.bits ^= other.bits; - } - - /// Inserts or removes the specified flags depending on the passed value. - #[inline] - pub fn set(&mut self, other: Self, value: bool) { - if value { - self.insert(other); - } else { - self.remove(other); - } - } - - /// Returns the intersection between the flags in `self` and - /// `other`. - /// - /// Specifically, the returned set contains only the flags which are - /// present in *both* `self` *and* `other`. - /// - /// This is equivalent to using the `&` operator (e.g. - /// [`ops::BitAnd`]), as in `flags & other`. - /// - /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html - #[inline] - #[must_use] - pub const fn intersection(self, other: Self) -> Self { - Self { bits: self.bits & other.bits } - } - - /// Returns the union of between the flags in `self` and `other`. - /// - /// Specifically, the returned set contains all flags which are - /// present in *either* `self` *or* `other`, including any which are - /// present in both (see [`Self::symmetric_difference`] if that - /// is undesirable). - /// - /// This is equivalent to using the `|` operator (e.g. - /// [`ops::BitOr`]), as in `flags | other`. - /// - /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html - #[inline] - #[must_use] - pub const fn union(self, other: Self) -> Self { - Self { bits: self.bits | other.bits } - } - - /// Returns the difference between the flags in `self` and `other`. - /// - /// Specifically, the returned set contains all flags present in - /// `self`, except for the ones present in `other`. - /// - /// It is also conceptually equivalent to the "bit-clear" operation: - /// `flags & !other` (and this syntax is also supported). - /// - /// This is equivalent to using the `-` operator (e.g. - /// [`ops::Sub`]), as in `flags - other`. - /// - /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html - #[inline] - #[must_use] - pub const fn difference(self, other: Self) -> Self { - Self { bits: self.bits & !other.bits } - } - - /// Returns the [symmetric difference][sym-diff] between the flags - /// in `self` and `other`. - /// - /// Specifically, the returned set contains the flags present which - /// are present in `self` or `other`, but that are not present in - /// both. Equivalently, it contains the flags present in *exactly - /// one* of the sets `self` and `other`. - /// - /// This is equivalent to using the `^` operator (e.g. - /// [`ops::BitXor`]), as in `flags ^ other`. - /// - /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference - /// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html - #[inline] - #[must_use] - pub const fn symmetric_difference(self, other: Self) -> Self { - Self { bits: self.bits ^ other.bits } - } - - /// Returns the complement of this set of flags. - /// - /// Specifically, the returned set contains all the flags which are - /// not set in `self`, but which are allowed for this type. - /// - /// Alternatively, it can be thought of as the set difference - /// between [`Self::all()`] and `self` (e.g. `Self::all() - self`) - /// - /// This is equivalent to using the `!` operator (e.g. - /// [`ops::Not`]), as in `!flags`. - /// - /// [`Self::all()`]: Self::all - /// [`ops::Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html - #[inline] - #[must_use] - pub const fn complement(self) -> Self { - Self::from_bits_truncate(!self.bits) - } - - } - - impl $crate::_core::ops::BitOr for $BitFlags { - type Output = Self; - - /// Returns the union of the two sets of flags. - #[inline] - fn bitor(self, other: $BitFlags) -> Self { - Self { bits: self.bits | other.bits } - } - } - - impl $crate::_core::ops::BitOrAssign for $BitFlags { - /// Adds the set of flags. - #[inline] - fn bitor_assign(&mut self, other: Self) { - self.bits |= other.bits; - } - } - - impl $crate::_core::ops::BitXor for $BitFlags { - type Output = Self; - - /// Returns the left flags, but with all the right flags toggled. - #[inline] - fn bitxor(self, other: Self) -> Self { - Self { bits: self.bits ^ other.bits } - } - } - - impl $crate::_core::ops::BitXorAssign for $BitFlags { - /// Toggles the set of flags. - #[inline] - fn bitxor_assign(&mut self, other: Self) { - self.bits ^= other.bits; - } - } - - impl $crate::_core::ops::BitAnd for $BitFlags { - type Output = Self; - - /// Returns the intersection between the two sets of flags. - #[inline] - fn bitand(self, other: Self) -> Self { - Self { bits: self.bits & other.bits } - } - } - - impl $crate::_core::ops::BitAndAssign for $BitFlags { - /// Disables all flags disabled in the set. - #[inline] - fn bitand_assign(&mut self, other: Self) { - self.bits &= other.bits; - } - } - - impl $crate::_core::ops::Sub for $BitFlags { - type Output = Self; - - /// Returns the set difference of the two sets of flags. - #[inline] - fn sub(self, other: Self) -> Self { - Self { bits: self.bits & !other.bits } - } - } - - impl $crate::_core::ops::SubAssign for $BitFlags { - /// Disables all flags enabled in the set. - #[inline] - fn sub_assign(&mut self, other: Self) { - self.bits &= !other.bits; - } - } - - impl $crate::_core::ops::Not for $BitFlags { - type Output = Self; - - /// Returns the complement of this set of flags. - #[inline] - fn not(self) -> Self { - Self { bits: !self.bits } & Self::all() - } - } - - impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags { - fn extend<T: $crate::_core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) { - for item in iterator { - self.insert(item) - } - } - } - - impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags { - fn from_iter<T: $crate::_core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self { - let mut result = Self::empty(); - result.extend(iterator); - result - } - } - }; - - // Every attribute that the user writes on a const is applied to the - // corresponding const that we generate, but within the implementation of - // Debug and all() we want to ignore everything but #[cfg] attributes. In - // particular, including a #[deprecated] attribute on those items would fail - // to compile. - // https://github.com/bitflags/bitflags/issues/109 - // - // Input: - // - // ? #[cfg(feature = "advanced")] - // ? #[deprecated(note = "Use something else.")] - // ? #[doc = r"High quality documentation."] - // fn f() -> i32 { /* ... */ } - // - // Output: - // - // #[cfg(feature = "advanced")] - // fn f() -> i32 { /* ... */ } - ( - $(#[$filtered:meta])* - ? #[cfg $($cfgargs:tt)*] - $(? #[$rest:ident $($restargs:tt)*])* - fn $($item:tt)* - ) => { - __impl_bitflags! { - $(#[$filtered])* - #[cfg $($cfgargs)*] - $(? #[$rest $($restargs)*])* - fn $($item)* - } - }; - ( - $(#[$filtered:meta])* - // $next != `cfg` - ? #[$next:ident $($nextargs:tt)*] - $(? #[$rest:ident $($restargs:tt)*])* - fn $($item:tt)* - ) => { - __impl_bitflags! { - $(#[$filtered])* - // $next filtered out - $(? #[$rest $($restargs)*])* - fn $($item)* - } - }; - ( - $(#[$filtered:meta])* - fn $($item:tt)* - ) => { - $(#[$filtered])* - fn $($item)* - }; - - // Every attribute that the user writes on a const is applied to the - // corresponding const that we generate, but within the implementation of - // Debug and all() we want to ignore everything but #[cfg] attributes. In - // particular, including a #[deprecated] attribute on those items would fail - // to compile. - // https://github.com/bitflags/bitflags/issues/109 - // - // const version - // - // Input: - // - // ? #[cfg(feature = "advanced")] - // ? #[deprecated(note = "Use something else.")] - // ? #[doc = r"High quality documentation."] - // const f: i32 { /* ... */ } - // - // Output: - // - // #[cfg(feature = "advanced")] - // const f: i32 { /* ... */ } - ( - $(#[$filtered:meta])* - ? #[cfg $($cfgargs:tt)*] - $(? #[$rest:ident $($restargs:tt)*])* - const $($item:tt)* - ) => { - __impl_bitflags! { - $(#[$filtered])* - #[cfg $($cfgargs)*] - $(? #[$rest $($restargs)*])* - const $($item)* - } - }; - ( - $(#[$filtered:meta])* - // $next != `cfg` - ? #[$next:ident $($nextargs:tt)*] - $(? #[$rest:ident $($restargs:tt)*])* - const $($item:tt)* - ) => { - __impl_bitflags! { - $(#[$filtered])* - // $next filtered out - $(? #[$rest $($restargs)*])* - const $($item)* + bitflags! { + $($t)* } }; - ( - $(#[$filtered:meta])* - const $($item:tt)* - ) => { - $(#[$filtered])* - const $($item)* - }; + () => {}; } +#[macro_use] +mod public; +#[macro_use] +mod internal; +#[macro_use] +mod external; + #[cfg(feature = "example_generated")] pub mod example_generated; #[cfg(test)] mod tests { - use std::collections::hash_map::DefaultHasher; - use std::hash::{Hash, Hasher}; + use std::{ + collections::hash_map::DefaultHasher, + fmt, + hash::{Hash, Hasher}, + str, + }; bitflags! { #[doc = "> The first principle is that you must not fool yourself — and"] #[doc = "> you are the easiest person to fool."] #[doc = "> "] #[doc = "> - Richard Feynman"] - #[derive(Default)] + #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] struct Flags: u32 { const A = 0b00000001; #[doc = "<pcwalton> macros are way better at generating code than trans is"] @@ -953,28 +664,56 @@ mod tests { #[doc = "* cmr bed"] #[doc = "* strcat table"] #[doc = "<strcat> wait what?"] - const ABC = Self::A.bits | Self::B.bits | Self::C.bits; + const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits(); } + #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] struct _CfgFlags: u32 { #[cfg(unix)] const _CFG_A = 0b01; #[cfg(windows)] const _CFG_B = 0b01; #[cfg(unix)] - const _CFG_C = Self::_CFG_A.bits | 0b10; + const _CFG_C = Self::_CFG_A.bits() | 0b10; } + #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] struct AnotherSetOfFlags: i8 { const ANOTHER_FLAG = -1_i8; } + #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] struct LongFlags: u32 { const LONG_A = 0b1111111111111111; } } bitflags! { + #[derive(Debug, PartialEq, Eq)] + struct FmtFlags: u16 { + const 고양이 = 0b0000_0001; + const 개 = 0b0000_0010; + const 물고기 = 0b0000_0100; + const 물고기_고양이 = Self::고양이.bits() | Self::물고기.bits(); + } + } + + impl str::FromStr for FmtFlags { + type Err = crate::parser::ParseError; + + fn from_str(flags: &str) -> Result<Self, Self::Err> { + Ok(Self(flags.parse()?)) + } + } + + impl fmt::Display for FmtFlags { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } + } + + bitflags! { + #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] struct EmptyFlags: u32 { } } @@ -1027,28 +766,19 @@ mod tests { } #[test] - fn test_from_bits_unchecked() { - let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; - assert_eq!(unsafe { Flags::from_bits_unchecked(0) }, Flags::empty()); - assert_eq!(unsafe { Flags::from_bits_unchecked(0b1) }, Flags::A); - assert_eq!(unsafe { Flags::from_bits_unchecked(0b10) }, Flags::B); + fn test_from_bits_retain() { + let extra = Flags::from_bits_retain(0b1000); + assert_eq!(Flags::from_bits_retain(0), Flags::empty()); + assert_eq!(Flags::from_bits_retain(0b1), Flags::A); + assert_eq!(Flags::from_bits_retain(0b10), Flags::B); - assert_eq!( - unsafe { Flags::from_bits_unchecked(0b11) }, - (Flags::A | Flags::B) - ); - assert_eq!( - unsafe { Flags::from_bits_unchecked(0b1000) }, - (extra | Flags::empty()) - ); - assert_eq!( - unsafe { Flags::from_bits_unchecked(0b1001) }, - (extra | Flags::A) - ); + assert_eq!(Flags::from_bits_retain(0b11), (Flags::A | Flags::B)); + assert_eq!(Flags::from_bits_retain(0b1000), (extra | Flags::empty())); + assert_eq!(Flags::from_bits_retain(0b1001), (extra | Flags::A)); - let extra = unsafe { EmptyFlags::from_bits_unchecked(0b1000) }; + let extra = EmptyFlags::from_bits_retain(0b1000); assert_eq!( - unsafe { EmptyFlags::from_bits_unchecked(0b1000) }, + EmptyFlags::from_bits_retain(0b1000), (extra | EmptyFlags::empty()) ); } @@ -1071,7 +801,7 @@ mod tests { assert!(!Flags::A.is_all()); assert!(Flags::ABC.is_all()); - let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; + let extra = Flags::from_bits_retain(0b1000); assert!(!extra.is_all()); assert!(!(Flags::A | extra).is_all()); assert!((Flags::ABC | extra).is_all()); @@ -1169,7 +899,7 @@ mod tests { #[test] fn test_operators_unchecked() { - let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; + let extra = Flags::from_bits_retain(0b1000); let e1 = Flags::A | Flags::C | extra; let e2 = Flags::B | Flags::C; assert_eq!((e1 | e2), (Flags::ABC | extra)); // union @@ -1188,9 +918,9 @@ mod tests { let ab = Flags::A.union(Flags::B); let ac = Flags::A.union(Flags::C); let bc = Flags::B.union(Flags::C); - assert_eq!(ab.bits, 0b011); - assert_eq!(bc.bits, 0b110); - assert_eq!(ac.bits, 0b101); + assert_eq!(ab.bits(), 0b011); + assert_eq!(bc.bits(), 0b110); + assert_eq!(ac.bits(), 0b101); assert_eq!(ab, Flags::B.union(Flags::A)); assert_eq!(ac, Flags::C.union(Flags::A)); @@ -1235,15 +965,18 @@ mod tests { assert_eq!(UNION, Flags::A | Flags::C); assert_eq!(DIFFERENCE, Flags::all() - Flags::A); assert_eq!(COMPLEMENT, !Flags::C); - assert_eq!(SYM_DIFFERENCE, (Flags::A | Flags::C) ^ (Flags::all() - Flags::A)); + assert_eq!( + SYM_DIFFERENCE, + (Flags::A | Flags::C) ^ (Flags::all() - Flags::A) + ); } #[test] fn test_set_ops_unchecked() { - let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; + let extra = Flags::from_bits_retain(0b1000); let e1 = Flags::A.union(Flags::C).union(extra); let e2 = Flags::B.union(Flags::C); - assert_eq!(e1.bits, 0b1101); + assert_eq!(e1.bits(), 0b1101); assert_eq!(e1.union(e2), (Flags::ABC | extra)); assert_eq!(e1.intersection(e2), Flags::C); assert_eq!(e1.difference(e2), Flags::A | extra); @@ -1257,11 +990,12 @@ mod tests { fn test_set_ops_exhaustive() { // Define a flag that contains gaps to help exercise edge-cases, // especially around "unknown" flags (e.g. ones outside of `all()` - // `from_bits_unchecked`). + // `from_bits_retain`). // - when lhs and rhs both have different sets of unknown flags. // - unknown flags at both ends, and in the middle // - cases with "gaps". bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] struct Test: u16 { // Intentionally no `A` const B = 0b000000010; @@ -1274,13 +1008,12 @@ mod tests { const I = 0b100000000; } } - let iter_test_flags = - || (0..=0b111_1111_1111).map(|bits| unsafe { Test::from_bits_unchecked(bits) }); + let iter_test_flags = || (0..=0b111_1111_1111).map(|bits| Test::from_bits_retain(bits)); for a in iter_test_flags() { assert_eq!( a.complement(), - Test::from_bits_truncate(!a.bits), + Test::from_bits_truncate(!a.bits()), "wrong result: !({:?})", a, ); @@ -1289,37 +1022,37 @@ mod tests { // Check that the named operations produce the expected bitwise // values. assert_eq!( - a.union(b).bits, - a.bits | b.bits, + a.union(b).bits(), + a.bits() | b.bits(), "wrong result: `{:?}` | `{:?}`", a, b, ); assert_eq!( - a.intersection(b).bits, - a.bits & b.bits, + a.intersection(b).bits(), + a.bits() & b.bits(), "wrong result: `{:?}` & `{:?}`", a, b, ); assert_eq!( - a.symmetric_difference(b).bits, - a.bits ^ b.bits, + a.symmetric_difference(b).bits(), + a.bits() ^ b.bits(), "wrong result: `{:?}` ^ `{:?}`", a, b, ); assert_eq!( - a.difference(b).bits, - a.bits & !b.bits, + a.difference(b).bits(), + a.bits() & !b.bits(), "wrong result: `{:?}` - `{:?}`", a, b, ); // Note: Difference is checked as both `a - b` and `b - a` assert_eq!( - b.difference(a).bits, - b.bits & !a.bits, + b.difference(a).bits(), + b.bits() & !a.bits(), "wrong result: `{:?}` - `{:?}`", b, a, @@ -1488,26 +1221,108 @@ mod tests { #[test] fn test_debug() { - assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); - assert_eq!(format!("{:?}", Flags::empty()), "(empty)"); - assert_eq!(format!("{:?}", Flags::ABC), "A | B | C | ABC"); - let extra = unsafe { Flags::from_bits_unchecked(0xb8) }; - assert_eq!(format!("{:?}", extra), "0xb8"); - assert_eq!(format!("{:?}", Flags::A | extra), "A | 0xb8"); + assert_eq!(format!("{:?}", Flags::A | Flags::B), "Flags(A | B)"); + assert_eq!(format!("{:?}", Flags::empty()), "Flags(0x0)"); + assert_eq!(format!("{:?}", Flags::ABC), "Flags(A | B | C)"); + + let extra = Flags::from_bits_retain(0xb8); + + assert_eq!(format!("{:?}", extra), "Flags(0xb8)"); + assert_eq!(format!("{:?}", Flags::A | extra), "Flags(A | 0xb8)"); assert_eq!( format!("{:?}", Flags::ABC | extra), - "A | B | C | ABC | 0xb8" + "Flags(A | B | C | ABC | 0xb8)" ); - assert_eq!(format!("{:?}", EmptyFlags::empty()), "(empty)"); + assert_eq!(format!("{:?}", EmptyFlags::empty()), "EmptyFlags(0x0)"); + } + + #[test] + fn test_display_from_str_roundtrip() { + fn format_parse_case<T: fmt::Debug + fmt::Display + str::FromStr + PartialEq>(flags: T) where <T as str::FromStr>::Err: fmt::Display { + assert_eq!(flags, { + match flags.to_string().parse::<T>() { + Ok(flags) => flags, + Err(e) => panic!("failed to parse `{}`: {}", flags, e), + } + }); + } + + fn parse_case<T: fmt::Debug + str::FromStr + PartialEq>(expected: T, flags: &str) where <T as str::FromStr>::Err: fmt::Display + fmt::Debug { + assert_eq!(expected, flags.parse::<T>().unwrap()); + } + + bitflags! { + #[derive(Debug, Eq, PartialEq)] + pub struct MultiBitFmtFlags: u8 { + const A = 0b0000_0001u8; + const B = 0b0001_1110u8; + } + } + + impl fmt::Display for MultiBitFmtFlags { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } + } + + impl str::FromStr for MultiBitFmtFlags { + type Err = crate::parser::ParseError; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(MultiBitFmtFlags(s.parse()?)) + } + } + + format_parse_case(FmtFlags::empty()); + format_parse_case(FmtFlags::all()); + format_parse_case(FmtFlags::고양이); + format_parse_case(FmtFlags::고양이 | FmtFlags::개); + format_parse_case(FmtFlags::물고기_고양이); + format_parse_case(FmtFlags::from_bits_retain(0xb8)); + format_parse_case(FmtFlags::from_bits_retain(0x20)); + format_parse_case(MultiBitFmtFlags::from_bits_retain(3)); + + parse_case(FmtFlags::empty(), ""); + parse_case(FmtFlags::empty(), " \r\n\t"); + parse_case(FmtFlags::empty(), "0x0"); + parse_case(FmtFlags::empty(), "0x0"); + + parse_case(FmtFlags::고양이, "고양이"); + parse_case(FmtFlags::고양이, " 고양이 "); + parse_case(FmtFlags::고양이, "고양이 | 고양이 | 고양이"); + parse_case(FmtFlags::고양이, "0x01"); + + parse_case(FmtFlags::고양이 | FmtFlags::개, "고양이 | 개"); + parse_case(FmtFlags::고양이 | FmtFlags::개, "고양이|개"); + parse_case(FmtFlags::고양이 | FmtFlags::개, "\n고양이|개 "); + + parse_case(FmtFlags::고양이 | FmtFlags::물고기, "물고기_고양이"); + } + + #[test] + fn test_from_str_err() { + fn parse_case(pat: &str, flags: &str) { + let err = flags.parse::<FmtFlags>().unwrap_err().to_string(); + assert!(err.contains(pat), "`{}` not found in error `{}`", pat, err); + } + + parse_case("empty flag", "|"); + parse_case("empty flag", "|||"); + parse_case("empty flag", "고양이 |"); + parse_case("unrecognized named flag", "NOT_A_FLAG"); + parse_case("unrecognized named flag", "고양이 개"); + parse_case("unrecognized named flag", "고양이 | NOT_A_FLAG"); + parse_case("invalid hex flag", "0xhi"); + parse_case("invalid hex flag", "고양이 | 0xhi"); } #[test] fn test_binary() { assert_eq!(format!("{:b}", Flags::ABC), "111"); assert_eq!(format!("{:#b}", Flags::ABC), "0b111"); - let extra = unsafe { Flags::from_bits_unchecked(0b1010000) }; + let extra = Flags::from_bits_retain(0b1010000); assert_eq!(format!("{:b}", Flags::ABC | extra), "1010111"); assert_eq!(format!("{:#b}", Flags::ABC | extra), "0b1010111"); } @@ -1516,7 +1331,7 @@ mod tests { fn test_octal() { assert_eq!(format!("{:o}", LongFlags::LONG_A), "177777"); assert_eq!(format!("{:#o}", LongFlags::LONG_A), "0o177777"); - let extra = unsafe { LongFlags::from_bits_unchecked(0o5000000) }; + let extra = LongFlags::from_bits_retain(0o5000000); assert_eq!(format!("{:o}", LongFlags::LONG_A | extra), "5177777"); assert_eq!(format!("{:#o}", LongFlags::LONG_A | extra), "0o5177777"); } @@ -1525,7 +1340,7 @@ mod tests { fn test_lowerhex() { assert_eq!(format!("{:x}", LongFlags::LONG_A), "ffff"); assert_eq!(format!("{:#x}", LongFlags::LONG_A), "0xffff"); - let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) }; + let extra = LongFlags::from_bits_retain(0xe00000); assert_eq!(format!("{:x}", LongFlags::LONG_A | extra), "e0ffff"); assert_eq!(format!("{:#x}", LongFlags::LONG_A | extra), "0xe0ffff"); } @@ -1534,17 +1349,19 @@ mod tests { fn test_upperhex() { assert_eq!(format!("{:X}", LongFlags::LONG_A), "FFFF"); assert_eq!(format!("{:#X}", LongFlags::LONG_A), "0xFFFF"); - let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) }; + let extra = LongFlags::from_bits_retain(0xe00000); assert_eq!(format!("{:X}", LongFlags::LONG_A | extra), "E0FFFF"); assert_eq!(format!("{:#X}", LongFlags::LONG_A | extra), "0xE0FFFF"); } mod submodule { bitflags! { + #[derive(Clone, Copy)] pub struct PublicFlags: i8 { const X = 0; } + #[derive(Clone, Copy)] struct PrivateFlags: i8 { const Y = 0; } @@ -1568,6 +1385,7 @@ mod tests { bitflags! { /// baz + #[derive(Clone, Copy)] struct Flags: foo::Bar { const A = 0b00000001; #[cfg(foo)] @@ -1581,19 +1399,21 @@ mod tests { #[test] fn test_in_function() { bitflags! { - struct Flags: u8 { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + struct Flags: u8 { const A = 1; #[cfg(any())] // false const B = 2; } } assert_eq!(Flags::all(), Flags::A); - assert_eq!(format!("{:?}", Flags::A), "A"); + assert_eq!(format!("{:?}", Flags::A), "Flags(A)"); } #[test] fn test_deprecated() { bitflags! { + #[derive(Clone, Copy)] pub struct TestFlags: u32 { #[deprecated(note = "Use something else.")] const ONE = 1; @@ -1605,6 +1425,7 @@ mod tests { fn test_pub_crate() { mod module { bitflags! { + #[derive(Clone, Copy)] pub (crate) struct Test: u8 { const FOO = 1; } @@ -1621,6 +1442,7 @@ mod tests { bitflags! { // `pub (in super)` means only the module `module` will // be able to access this. + #[derive(Clone, Copy)] pub (in super) struct Test: u8 { const FOO = 1; } @@ -1646,6 +1468,7 @@ mod tests { #[test] fn test_zero_value_flags() { bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] struct Flags: u32 { const NONE = 0b0; const SOME = 0b1; @@ -1656,8 +1479,7 @@ mod tests { assert!(Flags::SOME.contains(Flags::NONE)); assert!(Flags::NONE.is_empty()); - assert_eq!(format!("{:?}", Flags::empty()), "NONE"); - assert_eq!(format!("{:?}", Flags::SOME), "SOME"); + assert_eq!(format!("{:?}", Flags::SOME), "Flags(NONE | SOME)"); } #[test] @@ -1668,62 +1490,201 @@ mod tests { #[test] fn test_u128_bitflags() { bitflags! { - struct Flags128: u128 { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + struct Flags: u128 { const A = 0x0000_0000_0000_0000_0000_0000_0000_0001; const B = 0x0000_0000_0000_1000_0000_0000_0000_0000; const C = 0x8000_0000_0000_0000_0000_0000_0000_0000; - const ABC = Self::A.bits | Self::B.bits | Self::C.bits; + const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits(); } } - assert_eq!(Flags128::ABC, Flags128::A | Flags128::B | Flags128::C); - assert_eq!(Flags128::A.bits, 0x0000_0000_0000_0000_0000_0000_0000_0001); - assert_eq!(Flags128::B.bits, 0x0000_0000_0000_1000_0000_0000_0000_0000); - assert_eq!(Flags128::C.bits, 0x8000_0000_0000_0000_0000_0000_0000_0000); - assert_eq!( - Flags128::ABC.bits, - 0x8000_0000_0000_1000_0000_0000_0000_0001 - ); - assert_eq!(format!("{:?}", Flags128::A), "A"); - assert_eq!(format!("{:?}", Flags128::B), "B"); - assert_eq!(format!("{:?}", Flags128::C), "C"); - assert_eq!(format!("{:?}", Flags128::ABC), "A | B | C | ABC"); + assert_eq!(Flags::ABC, Flags::A | Flags::B | Flags::C); + assert_eq!(Flags::A.bits(), 0x0000_0000_0000_0000_0000_0000_0000_0001); + assert_eq!(Flags::B.bits(), 0x0000_0000_0000_1000_0000_0000_0000_0000); + assert_eq!(Flags::C.bits(), 0x8000_0000_0000_0000_0000_0000_0000_0000); + assert_eq!(Flags::ABC.bits(), 0x8000_0000_0000_1000_0000_0000_0000_0001); + assert_eq!(format!("{:?}", Flags::A), "Flags(A)"); + assert_eq!(format!("{:?}", Flags::B), "Flags(B)"); + assert_eq!(format!("{:?}", Flags::C), "Flags(C)"); + assert_eq!(format!("{:?}", Flags::ABC), "Flags(A | B | C)"); } #[test] - fn test_serde_bitflags_serialize() { - let flags = SerdeFlags::A | SerdeFlags::B; + fn test_from_bits_edge_cases() { + bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + struct Flags: u8 { + const A = 0b00000001; + const BC = 0b00000110; + } + } - let serialized = serde_json::to_string(&flags).unwrap(); + let flags = Flags::from_bits(0b00000100); + assert_eq!(flags, None); + let flags = Flags::from_bits(0b00000101); + assert_eq!(flags, None); + } - assert_eq!(serialized, r#"{"bits":3}"#); + #[test] + fn test_from_bits_truncate_edge_cases() { + bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + struct Flags: u8 { + const A = 0b00000001; + const BC = 0b00000110; + } + } + + let flags = Flags::from_bits_truncate(0b00000100); + assert_eq!(flags, Flags::empty()); + let flags = Flags::from_bits_truncate(0b00000101); + assert_eq!(flags, Flags::A); } #[test] - fn test_serde_bitflags_deserialize() { - let deserialized: SerdeFlags = serde_json::from_str(r#"{"bits":12}"#).unwrap(); + fn test_iter() { + bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + struct Flags: u32 { + const ONE = 0b001; + const TWO = 0b010; + const THREE = 0b100; + #[cfg(windows)] + const FOUR_WIN = 0b1000; + #[cfg(unix)] + const FOUR_UNIX = 0b10000; + const FIVE = 0b01000100; + } + } + + let count = { + #[cfg(any(unix, windows))] + { + 5 + } + + #[cfg(not(any(unix, windows)))] + { + 4 + } + }; + + let flags = Flags::all(); + assert_eq!(flags.into_iter().count(), count); + + for flag in flags.into_iter() { + assert!(flags.contains(flag)); + } - let expected = SerdeFlags::C | SerdeFlags::D; + let mut iter = flags.iter_names(); - assert_eq!(deserialized.bits, expected.bits); + assert_eq!(iter.next().unwrap(), ("ONE", Flags::ONE)); + assert_eq!(iter.next().unwrap(), ("TWO", Flags::TWO)); + assert_eq!(iter.next().unwrap(), ("THREE", Flags::THREE)); + + #[cfg(unix)] + { + assert_eq!(iter.next().unwrap(), ("FOUR_UNIX", Flags::FOUR_UNIX)); + } + #[cfg(windows)] + { + assert_eq!(iter.next().unwrap(), ("FOUR_WIN", Flags::FOUR_WIN)); + } + + assert_eq!(iter.next().unwrap(), ("FIVE", Flags::FIVE)); + + assert_eq!(iter.next(), None); + + let flags = Flags::empty(); + assert_eq!(flags.into_iter().count(), 0); + + let flags = Flags::ONE | Flags::THREE; + assert_eq!(flags.into_iter().count(), 2); + + let mut iter = flags.iter_names(); + + assert_eq!(iter.next().unwrap(), ("ONE", Flags::ONE)); + assert_eq!(iter.next().unwrap(), ("THREE", Flags::THREE)); + assert_eq!(iter.next(), None); + + let flags = Flags::from_bits_retain(0b1000_0000); + assert_eq!(flags.into_iter().count(), 1); + assert_eq!(flags.iter_names().count(), 0); + } + + #[test] + fn into_iter_from_iter_roundtrip() { + let flags = Flags::ABC | Flags::from_bits_retain(0b1000_0000); + + assert_eq!(flags, flags.into_iter().collect::<Flags>()); } #[test] - fn test_serde_bitflags_roundtrip() { - let flags = SerdeFlags::A | SerdeFlags::B; + fn test_from_name() { + let flags = Flags::all(); - let deserialized: SerdeFlags = serde_json::from_str(&serde_json::to_string(&flags).unwrap()).unwrap(); + let mut rebuilt = Flags::empty(); - assert_eq!(deserialized.bits, flags.bits); + for (name, value) in flags.iter_names() { + assert_eq!(value, Flags::from_name(name).unwrap()); + + rebuilt |= Flags::from_name(name).unwrap(); + } + + assert_eq!(flags, rebuilt); } - bitflags! { - #[derive(serde::Serialize, serde::Deserialize)] - struct SerdeFlags: u32 { - const A = 1; - const B = 2; - const C = 4; - const D = 8; + #[test] + fn bits_types() { + bitflags! { + pub struct I8: i8 { + const A = 1; + } + + pub struct I16: i16 { + const A = 1; + } + + pub struct I32: i32 { + const A = 1; + } + + pub struct I64: i64 { + const A = 1; + } + + pub struct I128: i128 { + const A = 1; + } + + pub struct Isize: isize { + const A = 1; + } + + pub struct U8: u8 { + const A = 1; + } + + pub struct U16: u16 { + const A = 1; + } + + pub struct U32: u32 { + const A = 1; + } + + pub struct U64: u64 { + const A = 1; + } + + pub struct U128: u128 { + const A = 1; + } + + pub struct Usize: usize { + const A = 1; + } } } } |