diff --git a/src/bitflags_trait.rs b/src/bitflags_trait.rs new file mode 100644 index 00000000..0b8facbb --- /dev/null +++ b/src/bitflags_trait.rs @@ -0,0 +1,46 @@ +use core as _core; + +pub trait BitFlags { + type Bits; + /// Returns an empty set of flags. + fn empty() -> Self; + /// Returns the set containing all flags. + fn all() -> Self; + /// Returns the raw value of the flags currently stored. + fn bits(&self) -> Self::Bits; + /// Convert from underlying bit representation, unless that + /// representation contains bits that do not correspond to a flag. + fn from_bits(bits: Self::Bits) -> _core::option::Option + where Self: Sized; + /// Convert from underlying bit representation, dropping any bits + /// that do not correspond to flags. + fn from_bits_truncate(bits: Self::Bits) -> Self; + /// 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. + unsafe fn from_bits_unchecked(bits: Self::Bits) -> Self; + /// Returns `true` if no flags are currently stored. + fn is_empty(&self) -> bool; + /// Returns `true` if all flags are currently set. + fn is_all(&self) -> bool; + /// Returns `true` if there are flags common to both `self` and `other`. + fn intersects(&self, other: Self) -> bool; + /// Returns `true` all of the flags in `other` are contained within `self`. + fn contains(&self, other: Self) -> bool; + /// Inserts the specified flags in-place. + fn insert(&mut self, other: Self); + /// Removes the specified flags in-place. + fn remove(&mut self, other: Self); + /// Toggles the specified flags in-place. + fn toggle(&mut self, other: Self); + /// Inserts or removes the specified flags depending on the passed value. + fn set(&mut self, other: Self, value: bool); +} diff --git a/src/lib.rs b/src/lib.rs index 935e432f..75108972 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -281,7 +281,12 @@ #[doc(hidden)] pub extern crate core as _core; -/// The macro used to generate the flag structures. +#[doc(inline)] +pub use bitflags_trait::BitFlags; + +mod bitflags_trait; + +/// The macro used to generate the flag structure. /// /// See the [crate level docs](../bitflags/index.html) for complete documentation. /// @@ -820,6 +825,66 @@ macro_rules! __impl_bitflags { result } } + + impl $crate::BitFlags for $BitFlags { + type Bits = $T; + + fn empty() -> Self { + $BitFlags::empty() + } + + fn all() -> Self { + $BitFlags::all() + } + + fn bits(&self) -> $T { + $BitFlags::bits(self) + } + + fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> { + $BitFlags::from_bits(bits) + } + + fn from_bits_truncate(bits: $T) -> $BitFlags { + $BitFlags::from_bits_truncate(bits) + } + + unsafe fn from_bits_unchecked(bits: $T) -> $BitFlags { + $BitFlags::from_bits_unchecked(bits) + } + + fn is_empty(&self) -> bool { + $BitFlags::is_empty(self) + } + + fn is_all(&self) -> bool { + $BitFlags::is_all(self) + } + + fn intersects(&self, other: $BitFlags) -> bool { + $BitFlags::intersects(self, other) + } + + fn contains(&self, other: $BitFlags) -> bool { + $BitFlags::contains(self, other) + } + + fn insert(&mut self, other: $BitFlags) { + $BitFlags::insert(self, other) + } + + fn remove(&mut self, other: $BitFlags) { + $BitFlags::remove(self, other) + } + + fn toggle(&mut self, other: $BitFlags) { + $BitFlags::toggle(self, other) + } + + fn set(&mut self, other: $BitFlags, value: bool) { + $BitFlags::set(self, other, value) + } + } }; // Every attribute that the user writes on a const is applied to the