diff options
Diffstat (limited to 'vendor/bitflags/src/traits.rs')
-rw-r--r-- | vendor/bitflags/src/traits.rs | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/vendor/bitflags/src/traits.rs b/vendor/bitflags/src/traits.rs new file mode 100644 index 0000000..2823514 --- /dev/null +++ b/vendor/bitflags/src/traits.rs @@ -0,0 +1,430 @@ +use core::{ + fmt, + ops::{BitAnd, BitOr, BitXor, Not}, +}; + +use crate::{ + iter, + parser::{ParseError, ParseHex, WriteHex}, +}; + +/** +A defined flags value that may be named or unnamed. +*/ +pub struct Flag<B> { + name: &'static str, + value: B, +} + +impl<B> Flag<B> { + /** + Define a flag. + + If `name` is non-empty then the flag is named, otherwise it's unnamed. + */ + pub const fn new(name: &'static str, value: B) -> Self { + Flag { name, value } + } + + /** + Get the name of this flag. + + If the flag is unnamed then the returned string will be empty. + */ + pub const fn name(&self) -> &'static str { + self.name + } + + /** + Get the flags value of this flag. + */ + pub const fn value(&self) -> &B { + &self.value + } + + /** + Whether the flag is named. + + If [`Flag::name`] returns a non-empty string then this method will return `true`. + */ + pub const fn is_named(&self) -> bool { + !self.name.is_empty() + } + + /** + Whether the flag is unnamed. + + If [`Flag::name`] returns a non-empty string then this method will return `false`. + */ + pub const fn is_unnamed(&self) -> bool { + self.name.is_empty() + } +} + +/** +A set of defined flags using a bits type as storage. + +## Implementing `Flags` + +This trait is implemented by the [`bitflags`](macro.bitflags.html) macro: + +``` +use bitflags::bitflags; + +bitflags! { + struct MyFlags: u8 { + const A = 1; + const B = 1 << 1; + } +} +``` + +It can also be implemented manually: + +``` +use bitflags::{Flag, Flags}; + +struct MyFlags(u8); + +impl Flags for MyFlags { + const FLAGS: &'static [Flag<Self>] = &[ + Flag::new("A", MyFlags(1)), + Flag::new("B", MyFlags(1 << 1)), + ]; + + type Bits = u8; + + fn from_bits_retain(bits: Self::Bits) -> Self { + MyFlags(bits) + } + + fn bits(&self) -> Self::Bits { + self.0 + } +} +``` + +## Using `Flags` + +The `Flags` trait can be used generically to work with any flags types. In this example, +we can count the number of defined named flags: + +``` +# use bitflags::{bitflags, Flags}; +fn defined_flags<F: Flags>() -> usize { + F::FLAGS.iter().filter(|f| f.is_named()).count() +} + +bitflags! { + struct MyFlags: u8 { + const A = 1; + const B = 1 << 1; + const C = 1 << 2; + + const _ = !0; + } +} + +assert_eq!(3, defined_flags::<MyFlags>()); +``` +*/ +pub trait Flags: Sized + 'static { + /// The set of defined flags. + const FLAGS: &'static [Flag<Self>]; + + /// The underlying bits type. + type Bits: Bits; + + /// Get a flags value with all bits unset. + fn empty() -> Self { + Self::from_bits_retain(Self::Bits::EMPTY) + } + + /// Get a flags value with all known bits set. + fn all() -> Self { + let mut truncated = Self::Bits::EMPTY; + + for flag in Self::FLAGS.iter() { + truncated = truncated | flag.value().bits(); + } + + Self::from_bits_retain(truncated) + } + + /// Get the underlying bits value. + /// + /// The returned value is exactly the bits set in this flags value. + fn bits(&self) -> Self::Bits; + + /// Convert from a bits value. + /// + /// This method will return `None` if any unknown bits are set. + fn from_bits(bits: Self::Bits) -> Option<Self> { + let truncated = Self::from_bits_truncate(bits); + + if truncated.bits() == bits { + Some(truncated) + } else { + None + } + } + + /// Convert from a bits value, unsetting any unknown bits. + fn from_bits_truncate(bits: Self::Bits) -> Self { + Self::from_bits_retain(bits & Self::all().bits()) + } + + /// Convert from a bits value exactly. + fn from_bits_retain(bits: Self::Bits) -> Self; + + /// Get a flags value with the bits of a flag with the given name set. + /// + /// This method will return `None` if `name` is empty or doesn't + /// correspond to any named flag. + fn from_name(name: &str) -> Option<Self> { + // Don't parse empty names as empty flags + if name.is_empty() { + return None; + } + + for flag in Self::FLAGS { + if flag.name() == name { + return Some(Self::from_bits_retain(flag.value().bits())); + } + } + + None + } + + /// Yield a set of contained flags values. + /// + /// Each yielded flags value will correspond to a defined named flag. Any unknown bits + /// will be yielded together as a final flags value. + fn iter(&self) -> iter::Iter<Self> { + iter::Iter::new(self) + } + + /// Yield a set of contained named flags values. + /// + /// This method is like [`Flags::iter`], except only yields bits in contained named flags. + /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded. + fn iter_names(&self) -> iter::IterNames<Self> { + iter::IterNames::new(self) + } + + /// Whether all bits in this flags value are unset. + fn is_empty(&self) -> bool { + self.bits() == Self::Bits::EMPTY + } + + /// Whether all known bits in this flags value are set. + fn is_all(&self) -> bool { + // NOTE: We check against `Self::all` here, not `Self::Bits::ALL` + // because the set of all flags may not use all bits + Self::all().bits() | self.bits() == self.bits() + } + + /// Whether any set bits in a source flags value are also set in a target flags value. + fn intersects(&self, other: Self) -> bool + where + Self: Sized, + { + self.bits() & other.bits() != Self::Bits::EMPTY + } + + /// Whether all set bits in a source flags value are also set in a target flags value. + fn contains(&self, other: Self) -> bool + where + Self: Sized, + { + self.bits() & other.bits() == other.bits() + } + + /// The bitwise or (`|`) of the bits in two flags values. + fn insert(&mut self, other: Self) + where + Self: Sized, + { + *self = Self::from_bits_retain(self.bits()).union(other); + } + + /// The intersection of a source flags value with the complement of a target flags value (`&!`). + /// + /// This method is not equivalent to `self & !other` when `other` has unknown bits set. + /// `remove` won't truncate `other`, but the `!` operator will. + fn remove(&mut self, other: Self) + where + Self: Sized, + { + *self = Self::from_bits_retain(self.bits()).difference(other); + } + + /// The bitwise exclusive-or (`^`) of the bits in two flags values. + fn toggle(&mut self, other: Self) + where + Self: Sized, + { + *self = Self::from_bits_retain(self.bits()).symmetric_difference(other); + } + + /// Call [`Flags::insert`] when `value` is `true` or [`Flags::remove`] when `value` is `false`. + fn set(&mut self, other: Self, value: bool) + where + Self: Sized, + { + if value { + self.insert(other); + } else { + self.remove(other); + } + } + + /// The bitwise and (`&`) of the bits in two flags values. + #[must_use] + fn intersection(self, other: Self) -> Self { + Self::from_bits_retain(self.bits() & other.bits()) + } + + /// The bitwise or (`|`) of the bits in two flags values. + #[must_use] + fn union(self, other: Self) -> Self { + Self::from_bits_retain(self.bits() | other.bits()) + } + + /// The intersection of a source flags value with the complement of a target flags value (`&!`). + /// + /// This method is not equivalent to `self & !other` when `other` has unknown bits set. + /// `difference` won't truncate `other`, but the `!` operator will. + #[must_use] + fn difference(self, other: Self) -> Self { + Self::from_bits_retain(self.bits() & !other.bits()) + } + + /// The bitwise exclusive-or (`^`) of the bits in two flags values. + #[must_use] + fn symmetric_difference(self, other: Self) -> Self { + Self::from_bits_retain(self.bits() ^ other.bits()) + } + + /// The bitwise negation (`!`) of the bits in a flags value, truncating the result. + #[must_use] + fn complement(self) -> Self { + Self::from_bits_truncate(!self.bits()) + } +} + +/** +A bits type that can be used as storage for a flags type. +*/ +pub trait Bits: + Clone + + Copy + + PartialEq + + BitAnd<Output = Self> + + BitOr<Output = Self> + + BitXor<Output = Self> + + Not<Output = Self> + + Sized + + 'static +{ + /// A value with all bits unset. + const EMPTY: Self; + + /// A value with all bits set. + const ALL: Self; +} + +// Not re-exported: prevent custom `Bits` impls being used in the `bitflags!` macro, +// or they may fail to compile based on crate features +pub trait Primitive {} + +macro_rules! impl_bits { + ($($u:ty, $i:ty,)*) => { + $( + impl Bits for $u { + const EMPTY: $u = 0; + const ALL: $u = <$u>::MAX; + } + + impl Bits for $i { + const EMPTY: $i = 0; + const ALL: $i = <$u>::MAX as $i; + } + + impl ParseHex for $u { + fn parse_hex(input: &str) -> Result<Self, ParseError> { + <$u>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input)) + } + } + + impl ParseHex for $i { + fn parse_hex(input: &str) -> Result<Self, ParseError> { + <$i>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input)) + } + } + + impl WriteHex for $u { + fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result { + write!(writer, "{:x}", self) + } + } + + impl WriteHex for $i { + fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result { + write!(writer, "{:x}", self) + } + } + + impl Primitive for $i {} + impl Primitive for $u {} + )* + } +} + +impl_bits! { + u8, i8, + u16, i16, + u32, i32, + u64, i64, + u128, i128, + usize, isize, +} + +/// A trait for referencing the `bitflags`-owned internal type +/// without exposing it publicly. +pub trait PublicFlags { + /// The type of the underlying storage. + type Primitive: Primitive; + + /// The type of the internal field on the generated flags type. + type Internal; +} + +#[doc(hidden)] +#[deprecated(note = "use the `Flags` trait instead")] +pub trait BitFlags: ImplementedByBitFlagsMacro + Flags { + /// An iterator over enabled flags in an instance of the type. + type Iter: Iterator<Item = Self>; + + /// An iterator over the raw names and bits for enabled flags in an instance of the type. + type IterNames: Iterator<Item = (&'static str, Self)>; +} + +#[allow(deprecated)] +impl<B: Flags> BitFlags for B { + type Iter = iter::Iter<Self>; + type IterNames = iter::IterNames<Self>; +} + +impl<B: Flags> ImplementedByBitFlagsMacro for B {} + +/// A marker trait that signals that an implementation of `BitFlags` came from the `bitflags!` macro. +/// +/// There's nothing stopping an end-user from implementing this trait, but we don't guarantee their +/// manual implementations won't break between non-breaking releases. +#[doc(hidden)] +pub trait ImplementedByBitFlagsMacro {} + +pub(crate) mod __private { + pub use super::{ImplementedByBitFlagsMacro, PublicFlags}; +} |