diff options
Diffstat (limited to 'src/public.rs')
-rw-r--r-- | src/public.rs | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/src/public.rs b/src/public.rs new file mode 100644 index 0000000..643f843 --- /dev/null +++ b/src/public.rs @@ -0,0 +1,467 @@ +//! Generate the user-facing flags type. +//! +//! The code here belongs to the end-user, so new trait implementations and methods can't be +//! added without potentially breaking users. + +/// Declare the user-facing bitflags struct. +/// +/// This type is guaranteed to be a newtype with a `bitflags`-facing type as its single field. +#[macro_export(local_inner_macros)] +#[doc(hidden)] +macro_rules! __declare_public_bitflags { + ( + $(#[$outer:meta])* + $vis:vis struct $BitFlags:ident; + ) => { + $(#[$outer])* + $vis struct $BitFlags(<$BitFlags as $crate::__private::PublicFlags>::Internal); + }; +} + +/// Implement functions on the public (user-facing) bitflags type. +/// +/// We need to be careful about adding new methods and trait implementations here because they +/// could conflict with items added by the end-user. +#[macro_export(local_inner_macros)] +#[doc(hidden)] +macro_rules! __impl_public_bitflags { + ( + $PublicBitFlags:ident: $T:ty, $InternalBitFlags:ident, $Iter:ident, $IterNames:ident; + ) => { + impl $crate::__private::core::fmt::Binary for $PublicBitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { + $crate::__private::core::fmt::Binary::fmt(&self.0, f) + } + } + + impl $crate::__private::core::fmt::Octal for $PublicBitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { + $crate::__private::core::fmt::Octal::fmt(&self.0, f) + } + } + + impl $crate::__private::core::fmt::LowerHex for $PublicBitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { + $crate::__private::core::fmt::LowerHex::fmt(&self.0, f) + } + } + + impl $crate::__private::core::fmt::UpperHex for $PublicBitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { + $crate::__private::core::fmt::UpperHex::fmt(&self.0, f) + } + } + + impl $PublicBitFlags { + /// Returns an empty set of flags. + #[inline] + pub const fn empty() -> Self { + Self($InternalBitFlags::empty()) + } + + /// Returns the set containing all flags. + #[inline] + pub const fn all() -> Self { + Self($InternalBitFlags::all()) + } + + /// Returns the raw value of the flags currently stored. + #[inline] + pub const fn bits(&self) -> $T { + self.0.bits() + } + + /// 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::__private::core::option::Option<Self> { + match $InternalBitFlags::from_bits(bits) { + $crate::__private::core::option::Option::Some(bits) => $crate::__private::core::option::Option::Some(Self(bits)), + $crate::__private::core::option::Option::None => $crate::__private::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($InternalBitFlags::from_bits_truncate(bits)) + } + + /// Convert from underlying bit representation, preserving all + /// bits (even those not corresponding to a defined flag). + #[inline] + pub const fn from_bits_retain(bits: $T) -> Self { + Self($InternalBitFlags::from_bits_retain(bits)) + } + + /// Get the value for a flag from its stringified name. + /// + /// Names are _case-sensitive_, so must correspond exactly to + /// the identifier given to the flag. + #[inline] + pub fn from_name(name: &str) -> $crate::__private::core::option::Option<Self> { + match $InternalBitFlags::from_name(name) { + $crate::__private::core::option::Option::Some(bits) => $crate::__private::core::option::Option::Some(Self(bits)), + $crate::__private::core::option::Option::None => $crate::__private::core::option::Option::None, + } + } + + /// Iterate over enabled flag values. + #[inline] + pub const fn iter(&self) -> $Iter { + self.0.iter() + } + + /// Iterate over enabled flag values with their stringified names. + #[inline] + pub const fn iter_names(&self) -> $IterNames { + self.0.iter_names() + } + + /// Returns `true` if no flags are currently stored. + #[inline] + pub const fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Returns `true` if all flags are currently set. + #[inline] + pub const fn is_all(&self) -> bool { + self.0.is_all() + } + + /// Returns `true` if there are flags common to both `self` and `other`. + #[inline] + pub const fn intersects(&self, other: Self) -> bool { + self.0.intersects(other.0) + } + + /// Returns `true` if all of the flags in `other` are contained within `self`. + #[inline] + pub const fn contains(&self, other: Self) -> bool { + self.0.contains(other.0) + } + + /// Inserts the specified flags in-place. + #[inline] + pub fn insert(&mut self, other: Self) { + self.0.insert(other.0) + } + + /// Removes the specified flags in-place. + #[inline] + pub fn remove(&mut self, other: Self) { + self.0.remove(other.0) + } + + /// Toggles the specified flags in-place. + #[inline] + pub fn toggle(&mut self, other: Self) { + self.0.toggle(other.0) + } + + /// Inserts or removes the specified flags depending on the passed value. + #[inline] + pub fn set(&mut self, other: Self, value: bool) { + self.0.set(other.0, value) + } + + /// 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(self.0.intersection(other.0)) + } + + /// 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(self.0.union(other.0)) + } + + /// 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(self.0.difference(other.0)) + } + + /// 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(self.0.symmetric_difference(other.0)) + } + + /// 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(self.0.complement()) + } + } + + impl $crate::__private::core::ops::BitOr for $PublicBitFlags { + type Output = Self; + + /// Returns the union of the two sets of flags. + #[inline] + fn bitor(self, other: $PublicBitFlags) -> Self { + self.union(other) + } + } + + impl $crate::__private::core::ops::BitOrAssign for $PublicBitFlags { + /// Adds the set of flags. + #[inline] + fn bitor_assign(&mut self, other: Self) { + self.0 = self.0.union(other.0); + } + } + + impl $crate::__private::core::ops::BitXor for $PublicBitFlags { + type Output = Self; + + /// Returns the left flags, but with all the right flags toggled. + #[inline] + fn bitxor(self, other: Self) -> Self { + self.symmetric_difference(other) + } + } + + impl $crate::__private::core::ops::BitXorAssign for $PublicBitFlags { + /// Toggles the set of flags. + #[inline] + fn bitxor_assign(&mut self, other: Self) { + self.0 = self.0.symmetric_difference(other.0); + } + } + + impl $crate::__private::core::ops::BitAnd for $PublicBitFlags { + type Output = Self; + + /// Returns the intersection between the two sets of flags. + #[inline] + fn bitand(self, other: Self) -> Self { + self.intersection(other) + } + } + + impl $crate::__private::core::ops::BitAndAssign for $PublicBitFlags { + /// Disables all flags disabled in the set. + #[inline] + fn bitand_assign(&mut self, other: Self) { + self.0 = self.0.intersection(other.0); + } + } + + impl $crate::__private::core::ops::Sub for $PublicBitFlags { + type Output = Self; + + /// Returns the set difference of the two sets of flags. + #[inline] + fn sub(self, other: Self) -> Self { + self.difference(other) + } + } + + impl $crate::__private::core::ops::SubAssign for $PublicBitFlags { + /// Disables all flags enabled in the set. + #[inline] + fn sub_assign(&mut self, other: Self) { + self.0 = self.0.difference(other.0); + } + } + + impl $crate::__private::core::ops::Not for $PublicBitFlags { + type Output = Self; + + /// Returns the complement of this set of flags. + #[inline] + fn not(self) -> Self { + self.complement() + } + } + + impl $crate::__private::core::iter::Extend<$PublicBitFlags> for $PublicBitFlags { + fn extend<T: $crate::__private::core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) { + for item in iterator { + self.insert(item) + } + } + } + + impl $crate::__private::core::iter::FromIterator<$PublicBitFlags> for $PublicBitFlags { + fn from_iter<T: $crate::__private::core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self { + use $crate::__private::core::iter::Extend; + + let mut result = Self::empty(); + result.extend(iterator); + result + } + } + + impl $crate::__private::core::iter::IntoIterator for $PublicBitFlags { + type Item = Self; + type IntoIter = $Iter; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } + } + + impl $crate::BitFlags for $PublicBitFlags { + type Bits = $T; + + type Iter = $Iter; + type IterNames = $IterNames; + + fn empty() -> Self { + $PublicBitFlags::empty() + } + + fn all() -> Self { + $PublicBitFlags::all() + } + + fn bits(&self) -> $T { + $PublicBitFlags::bits(self) + } + + fn from_bits(bits: $T) -> $crate::__private::core::option::Option<$PublicBitFlags> { + $PublicBitFlags::from_bits(bits) + } + + fn from_bits_truncate(bits: $T) -> $PublicBitFlags { + $PublicBitFlags::from_bits_truncate(bits) + } + + fn from_bits_retain(bits: $T) -> $PublicBitFlags { + $PublicBitFlags::from_bits_retain(bits) + } + + fn from_name(name: &str) -> $crate::__private::core::option::Option<$PublicBitFlags> { + $PublicBitFlags::from_name(name) + } + + fn iter(&self) -> Self::Iter { + $PublicBitFlags::iter(self) + } + + fn iter_names(&self) -> Self::IterNames { + $PublicBitFlags::iter_names(self) + } + + fn is_empty(&self) -> bool { + $PublicBitFlags::is_empty(self) + } + + fn is_all(&self) -> bool { + $PublicBitFlags::is_all(self) + } + + fn intersects(&self, other: $PublicBitFlags) -> bool { + $PublicBitFlags::intersects(self, other) + } + + fn contains(&self, other: $PublicBitFlags) -> bool { + $PublicBitFlags::contains(self, other) + } + + fn insert(&mut self, other: $PublicBitFlags) { + $PublicBitFlags::insert(self, other) + } + + fn remove(&mut self, other: $PublicBitFlags) { + $PublicBitFlags::remove(self, other) + } + + fn toggle(&mut self, other: $PublicBitFlags) { + $PublicBitFlags::toggle(self, other) + } + + fn set(&mut self, other: $PublicBitFlags, value: bool) { + $PublicBitFlags::set(self, other, value) + } + } + + impl $crate::__private::ImplementedByBitFlagsMacro for $PublicBitFlags {} + }; +} + +/// Implement constants on the public (user-facing) bitflags type. +#[macro_export(local_inner_macros)] +#[doc(hidden)] +macro_rules! __impl_public_bitflags_consts { + ( + $PublicBitFlags:ident { + $( + $(#[$attr:ident $($args:tt)*])* + $Flag:ident = $value:expr; + )* + } + ) => { + impl $PublicBitFlags { + $( + $(#[$attr $($args)*])* + pub const $Flag: Self = Self::from_bits_retain($value); + )* + } + }; +} |