blob: fd09a1a3f35303d87d37949518b8b31bf0250b16 [file] [log] [blame]
//! Generate the internal `bitflags`-facing flags type.
//!
//! The code generated here is owned by `bitflags`, but still part of its public API.
//! Changes to the types generated here need to be considered like any other public API change.
/// Declare the `bitflags`-facing bitflags struct.
///
/// This type is part of the `bitflags` crate's public API, but not part of the user's.
#[macro_export(local_inner_macros)]
#[doc(hidden)]
macro_rules! __declare_internal_bitflags {
(
$vis:vis struct $InternalBitFlags:ident: $T:ty;
$iter_vis:vis struct $Iter:ident;
$iter_names_vis:vis struct $IterNames:ident;
) => {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
$vis struct $InternalBitFlags {
bits: $T,
}
$iter_vis struct $Iter {
inner: $IterNames,
done: bool,
}
$iter_names_vis struct $IterNames {
idx: usize,
source: $InternalBitFlags,
state: $InternalBitFlags,
}
};
}
/// Implement functions on the private (bitflags-facing) bitflags type.
///
/// Methods and trait implementations can be freely added here without breaking end-users.
/// If we want to expose new functionality to `#[derive]`, this is the place to do it.
#[macro_export(local_inner_macros)]
#[doc(hidden)]
macro_rules! __impl_internal_bitflags {
(
$InternalBitFlags:ident: $T:ty, $BitFlags:ident, $Iter:ident, $IterNames:ident {
$(
$(#[$attr:ident $($args:tt)*])*
$Flag:ident;
)*
}
) => {
impl $crate::__private::PublicFlags for $BitFlags {
type Internal = $InternalBitFlags;
}
impl $crate::__private::core::default::Default for $InternalBitFlags {
#[inline]
fn default() -> Self {
$InternalBitFlags::empty()
}
}
impl $crate::__private::core::fmt::Debug for $InternalBitFlags {
fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
if self.is_empty() {
// If no flags are set then write an empty hex flag to avoid
// writing an empty string. In some contexts, like serialization,
// an empty string is preferrable, but it may be unexpected in
// others for a format not to produce any output.
//
// We can remove this `0x0` and remain compatible with `FromStr`,
// because an empty string will still parse to an empty set of flags,
// just like `0x0` does.
$crate::__private::core::write!(f, "{:#x}", <$T as $crate::__private::Bits>::EMPTY)
} else {
$crate::__private::core::fmt::Display::fmt(self, f)
}
}
}
impl $crate::__private::core::fmt::Display for $InternalBitFlags {
fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
// A formatter for bitflags that produces text output like:
//
// A | B | 0xf6
//
// The names of set flags are written in a bar-separated-format,
// followed by a hex number of any remaining bits that are set
// but don't correspond to any flags.
// Iterate over the valid flags
let mut first = true;
let mut iter = self.iter_names();
for (name, _) in &mut iter {
if !first {
f.write_str(" | ")?;
}
first = false;
f.write_str(name)?;
}
// Append any extra bits that correspond to flags to the end of the format
let extra_bits = iter.state.bits();
if extra_bits != <$T as $crate::__private::Bits>::EMPTY {
if !first {
f.write_str(" | ")?;
}
$crate::__private::core::write!(f, "{:#x}", extra_bits)?;
}
$crate::__private::core::fmt::Result::Ok(())
}
}
// The impl for `FromStr` should parse anything produced by `Display`
impl $crate::__private::core::str::FromStr for $InternalBitFlags {
type Err = $crate::parser::ParseError;
fn from_str(s: &str) -> $crate::__private::core::result::Result<Self, Self::Err> {
let s = s.trim();
let mut parsed_flags = Self::empty();
// If the input is empty then return an empty set of flags
if s.is_empty() {
return $crate::__private::core::result::Result::Ok(parsed_flags);
}
for flag in s.split('|') {
let flag = flag.trim();
// If the flag is empty then we've got missing input
if flag.is_empty() {
return $crate::__private::core::result::Result::Err($crate::parser::ParseError::empty_flag());
}
// If the flag starts with `0x` then it's a hex number
// Parse it directly to the underlying bits type
let parsed_flag = if let $crate::__private::core::option::Option::Some(flag) = flag.strip_prefix("0x") {
let bits = <$T>::from_str_radix(flag, 16).map_err(|_| $crate::parser::ParseError::invalid_hex_flag(flag))?;
Self::from_bits_retain(bits)
}
// Otherwise the flag is a name
// The generated flags type will determine whether
// or not it's a valid identifier
else {
Self::from_name(flag).ok_or_else(|| $crate::parser::ParseError::invalid_named_flag(flag))?
};
parsed_flags.insert(parsed_flag);
}
$crate::__private::core::result::Result::Ok(parsed_flags)
}
}
impl $crate::__private::core::fmt::Binary for $InternalBitFlags {
fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
$crate::__private::core::fmt::Binary::fmt(&self.bits(), f)
}
}
impl $crate::__private::core::fmt::Octal for $InternalBitFlags {
fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
$crate::__private::core::fmt::Octal::fmt(&self.bits(), f)
}
}
impl $crate::__private::core::fmt::LowerHex for $InternalBitFlags {
fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
$crate::__private::core::fmt::LowerHex::fmt(&self.bits(), f)
}
}
impl $crate::__private::core::fmt::UpperHex for $InternalBitFlags {
fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
$crate::__private::core::fmt::UpperHex::fmt(&self.bits(), f)
}
}
impl $InternalBitFlags {
#[inline]
pub const fn empty() -> Self {
Self { bits: <$T as $crate::__private::Bits>::EMPTY }
}
#[inline]
pub const fn all() -> Self {
Self::from_bits_truncate(<$T as $crate::__private::Bits>::ALL)
}
#[inline]
pub const fn bits(&self) -> $T {
self.bits
}
#[inline]
pub fn bits_mut(&mut self) -> &mut $T {
&mut self.bits
}
#[inline]
pub const fn from_bits(bits: $T) -> $crate::__private::core::option::Option<Self> {
let truncated = Self::from_bits_truncate(bits).bits;
if truncated == bits {
$crate::__private::core::option::Option::Some(Self { bits })
} else {
$crate::__private::core::option::Option::None
}
}
#[inline]
pub const fn from_bits_truncate(bits: $T) -> Self {
if bits == <$T as $crate::__private::Bits>::EMPTY {
return Self { bits }
}
let mut truncated = <$T as $crate::__private::Bits>::EMPTY;
$(
$(#[$attr $($args)*])*
if bits & $BitFlags::$Flag.bits() == $BitFlags::$Flag.bits() {
truncated |= $BitFlags::$Flag.bits()
}
)*
Self { bits: truncated }
}
#[inline]
pub const fn from_bits_retain(bits: $T) -> Self {
Self { bits }
}
#[inline]
pub fn from_name(name: &str) -> $crate::__private::core::option::Option<Self> {
match name {
$(
$(#[$attr $($args)*])*
$crate::__private::core::stringify!($Flag) => $crate::__private::core::option::Option::Some(Self { bits: $BitFlags::$Flag.bits() }),
)*
_ => $crate::__private::core::option::Option::None,
}
}
#[inline]
pub const fn iter(&self) -> $Iter {
$Iter {
inner: self.iter_names(),
done: false,
}
}
#[inline]
pub const fn iter_names(&self) -> $IterNames {
$IterNames {
idx: 0,
source: *self,
state: *self,
}
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.bits == Self::empty().bits
}
#[inline]
pub const fn is_all(&self) -> bool {
Self::all().bits | self.bits == self.bits
}
#[inline]
pub const fn intersects(&self, other: Self) -> bool {
!(Self { bits: self.bits & other.bits}).is_empty()
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
(self.bits & other.bits) == other.bits
}
#[inline]
pub fn insert(&mut self, other: Self) {
self.bits |= other.bits;
}
#[inline]
pub fn remove(&mut self, other: Self) {
self.bits &= !other.bits;
}
#[inline]
pub fn toggle(&mut self, other: Self) {
self.bits ^= other.bits;
}
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
if value {
self.insert(other);
} else {
self.remove(other);
}
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self { bits: self.bits & other.bits }
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self { bits: self.bits | other.bits }
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self { bits: self.bits & !other.bits }
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self { bits: self.bits ^ other.bits }
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self::from_bits_truncate(!self.bits)
}
}
impl $crate::__private::core::convert::AsRef<$T> for $InternalBitFlags {
fn as_ref(&self) -> &$T {
&self.bits
}
}
impl $crate::__private::core::convert::From<$T> for $InternalBitFlags {
fn from(bits: $T) -> Self {
Self::from_bits_retain(bits)
}
}
impl $crate::__private::core::iter::Iterator for $Iter {
type Item = $BitFlags;
fn next(&mut self) -> $crate::__private::core::option::Option<Self::Item> {
match self.inner.next().map(|(_, value)| value) {
$crate::__private::core::option::Option::Some(value) => $crate::__private::core::option::Option::Some(value),
$crate::__private::core::option::Option::None if !self.done => {
self.done = true;
// After iterating through valid names, if there are any bits left over
// then return one final value that includes them. This makes `into_iter`
// and `from_iter` roundtrip
if self.inner.state != $InternalBitFlags::empty() {
$crate::__private::core::option::Option::Some($BitFlags::from_bits_retain(self.inner.state.bits()))
} else {
$crate::__private::core::option::Option::None
}
},
_ => $crate::__private::core::option::Option::None,
}
}
}
impl $crate::__private::core::iter::Iterator for $IterNames {
type Item = (&'static str, $BitFlags);
fn next(&mut self) -> $crate::__private::core::option::Option<Self::Item> {
const NUM_FLAGS: usize = {
let mut num_flags = 0;
$(
$(#[$attr $($args)*])*
{
num_flags += 1;
}
)*
num_flags
};
const OPTIONS: [$T; NUM_FLAGS] = [
$(
$(#[$attr $($args)*])*
$BitFlags::$Flag.bits(),
)*
];
const OPTIONS_NAMES: [&'static str; NUM_FLAGS] = [
$(
$(#[$attr $($args)*])*
$crate::__private::core::stringify!($Flag),
)*
];
if self.state.is_empty() || NUM_FLAGS == 0 {
$crate::__private::core::option::Option::None
} else {
for (flag, flag_name) in OPTIONS[self.idx..NUM_FLAGS].iter().copied()
.zip(OPTIONS_NAMES[self.idx..NUM_FLAGS].iter().copied())
{
self.idx += 1;
// NOTE: We check whether the flag exists in self, but remove it from
// a different value. This ensure that overlapping flags are handled
// properly. Take the following example:
//
// const A: 0b00000001;
// const B: 0b00000101;
//
// Given the bits 0b00000101, both A and B are set. But if we removed A
// as we encountered it we'd be left with 0b00000100, which doesn't
// correspond to a valid flag on its own.
if self.source.contains($InternalBitFlags { bits: flag }) {
self.state.remove($InternalBitFlags { bits: flag });
return $crate::__private::core::option::Option::Some((flag_name, $BitFlags::from_bits_retain(flag)))
}
}
$crate::__private::core::option::Option::None
}
}
}
};
}