summaryrefslogtreecommitdiffstats
path: root/third_party/rust/bitflags/src
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/bitflags/src')
-rw-r--r--third_party/rust/bitflags/src/external.rs24
-rw-r--r--third_party/rust/bitflags/src/internal.rs10
-rw-r--r--third_party/rust/bitflags/src/lib.rs46
-rw-r--r--third_party/rust/bitflags/src/parser.rs85
-rw-r--r--third_party/rust/bitflags/src/public.rs42
-rw-r--r--third_party/rust/bitflags/src/tests/all.rs23
-rw-r--r--third_party/rust/bitflags/src/tests/bits.rs36
-rw-r--r--third_party/rust/bitflags/src/tests/complement.rs53
-rw-r--r--third_party/rust/bitflags/src/tests/contains.rs108
-rw-r--r--third_party/rust/bitflags/src/tests/difference.rs92
-rw-r--r--third_party/rust/bitflags/src/tests/empty.rs23
-rw-r--r--third_party/rust/bitflags/src/tests/eq.rs10
-rw-r--r--third_party/rust/bitflags/src/tests/extend.rs42
-rw-r--r--third_party/rust/bitflags/src/tests/flags.rs46
-rw-r--r--third_party/rust/bitflags/src/tests/fmt.rs97
-rw-r--r--third_party/rust/bitflags/src/tests/from_bits.rs45
-rw-r--r--third_party/rust/bitflags/src/tests/from_bits_retain.rs38
-rw-r--r--third_party/rust/bitflags/src/tests/from_bits_truncate.rs42
-rw-r--r--third_party/rust/bitflags/src/tests/from_name.rs42
-rw-r--r--third_party/rust/bitflags/src/tests/insert.rs91
-rw-r--r--third_party/rust/bitflags/src/tests/intersection.rs79
-rw-r--r--third_party/rust/bitflags/src/tests/intersects.rs91
-rw-r--r--third_party/rust/bitflags/src/tests/is_all.rs32
-rw-r--r--third_party/rust/bitflags/src/tests/is_empty.rs31
-rw-r--r--third_party/rust/bitflags/src/tests/iter.rs209
-rw-r--r--third_party/rust/bitflags/src/tests/parser.rs332
-rw-r--r--third_party/rust/bitflags/src/tests/remove.rs100
-rw-r--r--third_party/rust/bitflags/src/tests/symmetric_difference.rs110
-rw-r--r--third_party/rust/bitflags/src/tests/union.rs71
-rw-r--r--third_party/rust/bitflags/src/traits.rs1
30 files changed, 1993 insertions, 58 deletions
diff --git a/third_party/rust/bitflags/src/external.rs b/third_party/rust/bitflags/src/external.rs
index efeaa82796..716af83c0f 100644
--- a/third_party/rust/bitflags/src/external.rs
+++ b/third_party/rust/bitflags/src/external.rs
@@ -14,7 +14,7 @@ Next, re-export the library from the `__private` module here.
Next, define a macro like so:
```rust
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(feature = "serde")]
macro_rules! __impl_external_bitflags_my_library {
@@ -30,7 +30,7 @@ macro_rules! __impl_external_bitflags_my_library {
};
}
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "my_library"))]
macro_rules! __impl_external_bitflags_my_library {
@@ -77,7 +77,7 @@ pub(crate) mod __private {
}
/// Implements traits from external libraries for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_external_bitflags {
(
@@ -92,7 +92,7 @@ macro_rules! __impl_external_bitflags {
// Use `serde` as an example: generate code when the feature is available,
// and a no-op when it isn't
- __impl_external_bitflags_serde! {
+ $crate::__impl_external_bitflags_serde! {
$InternalBitFlags: $T, $PublicBitFlags {
$(
$(#[$inner $($args)*])*
@@ -101,7 +101,7 @@ macro_rules! __impl_external_bitflags {
}
}
- __impl_external_bitflags_arbitrary! {
+ $crate::__impl_external_bitflags_arbitrary! {
$InternalBitFlags: $T, $PublicBitFlags {
$(
$(#[$inner $($args)*])*
@@ -110,7 +110,7 @@ macro_rules! __impl_external_bitflags {
}
}
- __impl_external_bitflags_bytemuck! {
+ $crate::__impl_external_bitflags_bytemuck! {
$InternalBitFlags: $T, $PublicBitFlags {
$(
$(#[$inner $($args)*])*
@@ -125,7 +125,7 @@ macro_rules! __impl_external_bitflags {
pub mod serde;
/// Implement `Serialize` and `Deserialize` for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(feature = "serde")]
macro_rules! __impl_external_bitflags_serde {
@@ -161,7 +161,7 @@ macro_rules! __impl_external_bitflags_serde {
};
}
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "serde"))]
macro_rules! __impl_external_bitflags_serde {
@@ -182,7 +182,7 @@ pub mod arbitrary;
mod bytemuck;
/// Implement `Arbitrary` for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(feature = "arbitrary")]
macro_rules! __impl_external_bitflags_arbitrary {
@@ -204,7 +204,7 @@ macro_rules! __impl_external_bitflags_arbitrary {
};
}
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "arbitrary"))]
macro_rules! __impl_external_bitflags_arbitrary {
@@ -219,7 +219,7 @@ macro_rules! __impl_external_bitflags_arbitrary {
}
/// Implement `Pod` and `Zeroable` for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(feature = "bytemuck")]
macro_rules! __impl_external_bitflags_bytemuck {
@@ -247,7 +247,7 @@ macro_rules! __impl_external_bitflags_bytemuck {
};
}
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "bytemuck"))]
macro_rules! __impl_external_bitflags_bytemuck {
diff --git a/third_party/rust/bitflags/src/internal.rs b/third_party/rust/bitflags/src/internal.rs
index aca1ac4db1..87d01cc0cb 100644
--- a/third_party/rust/bitflags/src/internal.rs
+++ b/third_party/rust/bitflags/src/internal.rs
@@ -6,7 +6,7 @@
/// 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)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __declare_internal_bitflags {
(
@@ -25,7 +25,7 @@ macro_rules! __declare_internal_bitflags {
///
/// 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)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_internal_bitflags {
(
@@ -97,7 +97,7 @@ macro_rules! __impl_internal_bitflags {
// The internal flags type offers a similar API to the public one
- __impl_public_bitflags! {
+ $crate::__impl_public_bitflags! {
$InternalBitFlags: $T, $PublicBitFlags {
$(
$(#[$inner $($args)*])*
@@ -106,11 +106,11 @@ macro_rules! __impl_internal_bitflags {
}
}
- __impl_public_bitflags_ops! {
+ $crate::__impl_public_bitflags_ops! {
$InternalBitFlags
}
- __impl_public_bitflags_iter! {
+ $crate::__impl_public_bitflags_iter! {
$InternalBitFlags: $T, $PublicBitFlags
}
diff --git a/third_party/rust/bitflags/src/lib.rs b/third_party/rust/bitflags/src/lib.rs
index c8aff6873f..8f7225915e 100644
--- a/third_party/rust/bitflags/src/lib.rs
+++ b/third_party/rust/bitflags/src/lib.rs
@@ -17,7 +17,7 @@ Add `bitflags` to your `Cargo.toml`:
```toml
[dependencies.bitflags]
-version = "2.4.1"
+version = "2.5.0"
```
## Generating flags types
@@ -252,6 +252,8 @@ mod traits;
#[doc(hidden)]
pub mod __private {
+ #[allow(unused_imports)]
+ // Easier than conditionally checking any optional external dependencies
pub use crate::{external::__private::*, traits::__private::*};
pub use core;
@@ -441,7 +443,7 @@ bitflags! {
}
```
*/
-#[macro_export(local_inner_macros)]
+#[macro_export]
macro_rules! bitflags {
(
$(#[$outer:meta])*
@@ -456,13 +458,13 @@ macro_rules! bitflags {
) => {
// Declared in the scope of the `bitflags!` call
// This type appears in the end-user's API
- __declare_public_bitflags! {
+ $crate::__declare_public_bitflags! {
$(#[$outer])*
$vis struct $BitFlags
}
// Workaround for: https://github.com/bitflags/bitflags/issues/320
- __impl_public_bitflags_consts! {
+ $crate::__impl_public_bitflags_consts! {
$BitFlags: $T {
$(
$(#[$inner $($args)*])*
@@ -487,11 +489,11 @@ macro_rules! bitflags {
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! {
+ $crate::__declare_internal_bitflags! {
$vis struct InternalBitFlags: $T
}
- __impl_internal_bitflags! {
+ $crate::__impl_internal_bitflags! {
InternalBitFlags: $T, $BitFlags {
$(
$(#[$inner $($args)*])*
@@ -501,7 +503,7 @@ macro_rules! bitflags {
}
// This is where new library trait implementations can be added
- __impl_external_bitflags! {
+ $crate::__impl_external_bitflags! {
InternalBitFlags: $T, $BitFlags {
$(
$(#[$inner $($args)*])*
@@ -510,20 +512,20 @@ macro_rules! bitflags {
}
}
- __impl_public_bitflags_forward! {
+ $crate::__impl_public_bitflags_forward! {
$BitFlags: $T, InternalBitFlags
}
- __impl_public_bitflags_ops! {
+ $crate::__impl_public_bitflags_ops! {
$BitFlags
}
- __impl_public_bitflags_iter! {
+ $crate::__impl_public_bitflags_iter! {
$BitFlags: $T, $BitFlags
}
};
- bitflags! {
+ $crate::bitflags! {
$($t)*
}
};
@@ -537,7 +539,7 @@ macro_rules! bitflags {
$($t:tt)*
) => {
- __impl_public_bitflags_consts! {
+ $crate::__impl_public_bitflags_consts! {
$BitFlags: $T {
$(
$(#[$inner $($args)*])*
@@ -558,7 +560,7 @@ macro_rules! bitflags {
clippy::iter_without_into_iter,
)]
const _: () = {
- __impl_public_bitflags! {
+ $crate::__impl_public_bitflags! {
$BitFlags: $T, $BitFlags {
$(
$(#[$inner $($args)*])*
@@ -567,16 +569,16 @@ macro_rules! bitflags {
}
}
- __impl_public_bitflags_ops! {
+ $crate::__impl_public_bitflags_ops! {
$BitFlags
}
- __impl_public_bitflags_iter! {
+ $crate::__impl_public_bitflags_iter! {
$BitFlags: $T, $BitFlags
}
};
- bitflags! {
+ $crate::bitflags! {
$($t)*
}
};
@@ -587,7 +589,7 @@ macro_rules! bitflags {
///
/// 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)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_bitflags {
(
@@ -796,7 +798,7 @@ macro_rules! __impl_bitflags {
///
/// If you find yourself with an attribute that should be considered expression-safe
/// and isn't, it can be added here.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __bitflags_expr_safe_attrs {
// Entrypoint: Move all flags and all attributes into `unprocessed` lists
@@ -805,7 +807,7 @@ macro_rules! __bitflags_expr_safe_attrs {
$(#[$inner:ident $($args:tt)*])*
{ $e:expr }
) => {
- __bitflags_expr_safe_attrs! {
+ $crate::__bitflags_expr_safe_attrs! {
expr: { $e },
attrs: {
// All attributes start here
@@ -830,7 +832,7 @@ macro_rules! __bitflags_expr_safe_attrs {
processed: [$($expr:tt)*],
},
) => {
- __bitflags_expr_safe_attrs! {
+ $crate::__bitflags_expr_safe_attrs! {
expr: { $e },
attrs: {
unprocessed: [
@@ -857,7 +859,7 @@ macro_rules! __bitflags_expr_safe_attrs {
processed: [$($expr:tt)*],
},
) => {
- __bitflags_expr_safe_attrs! {
+ $crate::__bitflags_expr_safe_attrs! {
expr: { $e },
attrs: {
unprocessed: [
@@ -884,7 +886,7 @@ macro_rules! __bitflags_expr_safe_attrs {
}
/// Implement a flag, which may be a wildcard `_`.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __bitflags_flag {
(
diff --git a/third_party/rust/bitflags/src/parser.rs b/third_party/rust/bitflags/src/parser.rs
index 130dc2e1f8..34b432da39 100644
--- a/third_party/rust/bitflags/src/parser.rs
+++ b/third_party/rust/bitflags/src/parser.rs
@@ -77,8 +77,10 @@ where
fmt::Result::Ok(())
}
+#[cfg(feature = "serde")]
pub(crate) struct AsDisplay<'a, B>(pub(crate) &'a B);
+#[cfg(feature = "serde")]
impl<'a, B: Flags> fmt::Display for AsDisplay<'a, B>
where
B::Bits: WriteHex,
@@ -135,6 +137,89 @@ where
}
/**
+Write a flags value as text, ignoring any unknown bits.
+*/
+pub fn to_writer_truncate<B: Flags>(flags: &B, writer: impl Write) -> Result<(), fmt::Error>
+where
+ B::Bits: WriteHex,
+{
+ to_writer(&B::from_bits_truncate(flags.bits()), writer)
+}
+
+/**
+Parse a flags value from text.
+
+This function will fail on any names that don't correspond to defined flags.
+Unknown bits will be ignored.
+*/
+pub fn from_str_truncate<B: Flags>(input: &str) -> Result<B, ParseError>
+where
+ B::Bits: ParseHex,
+{
+ Ok(B::from_bits_truncate(from_str::<B>(input)?.bits()))
+}
+
+/**
+Write only the contained, defined, named flags in a flags value as text.
+*/
+pub fn to_writer_strict<B: Flags>(flags: &B, mut writer: impl Write) -> Result<(), fmt::Error> {
+ // This is a simplified version of `to_writer` that ignores
+ // any bits not corresponding to a named flag
+
+ let mut first = true;
+ let mut iter = flags.iter_names();
+ for (name, _) in &mut iter {
+ if !first {
+ writer.write_str(" | ")?;
+ }
+
+ first = false;
+ writer.write_str(name)?;
+ }
+
+ fmt::Result::Ok(())
+}
+
+/**
+Parse a flags value from text.
+
+This function will fail on any names that don't correspond to defined flags.
+This function will fail to parse hex values.
+*/
+pub fn from_str_strict<B: Flags>(input: &str) -> Result<B, ParseError> {
+ // This is a simplified version of `from_str` that ignores
+ // any bits not corresponding to a named flag
+
+ let mut parsed_flags = B::empty();
+
+ // If the input is empty then return an empty set of flags
+ if input.trim().is_empty() {
+ return Ok(parsed_flags);
+ }
+
+ for flag in input.split('|') {
+ let flag = flag.trim();
+
+ // If the flag is empty then we've got missing input
+ if flag.is_empty() {
+ return Err(ParseError::empty_flag());
+ }
+
+ // If the flag starts with `0x` then it's a hex number
+ // These aren't supported in the strict parser
+ if flag.starts_with("0x") {
+ return Err(ParseError::invalid_hex_flag("unsupported hex flag value"));
+ }
+
+ let parsed_flag = B::from_name(flag).ok_or_else(|| ParseError::invalid_named_flag(flag))?;
+
+ parsed_flags.insert(parsed_flag);
+ }
+
+ Ok(parsed_flags)
+}
+
+/**
Encode a value as a hex string.
Implementors of this trait should not write the `0x` prefix.
diff --git a/third_party/rust/bitflags/src/public.rs b/third_party/rust/bitflags/src/public.rs
index 967e0dacbf..dc2d726782 100644
--- a/third_party/rust/bitflags/src/public.rs
+++ b/third_party/rust/bitflags/src/public.rs
@@ -6,7 +6,7 @@
/// 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)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __declare_public_bitflags {
(
@@ -22,13 +22,13 @@ macro_rules! __declare_public_bitflags {
///
/// 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)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags_forward {
(
$PublicBitFlags:ident: $T:ty, $InternalBitFlags:ident
) => {
- __impl_bitflags! {
+ $crate::__impl_bitflags! {
$PublicBitFlags: $T {
fn empty() {
Self($InternalBitFlags::empty())
@@ -124,7 +124,7 @@ macro_rules! __impl_public_bitflags_forward {
///
/// 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)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags {
(
@@ -135,7 +135,7 @@ macro_rules! __impl_public_bitflags {
)*
}
) => {
- __impl_bitflags! {
+ $crate::__impl_bitflags! {
$BitFlags: $T {
fn empty() {
Self(<$T as $crate::Bits>::EMPTY)
@@ -146,7 +146,7 @@ macro_rules! __impl_public_bitflags {
let mut i = 0;
$(
- __bitflags_expr_safe_attrs!(
+ $crate::__bitflags_expr_safe_attrs!(
$(#[$inner $($args)*])*
{{
let flag = <$PublicBitFlags as $crate::Flags>::FLAGS[i].value().bits();
@@ -185,10 +185,10 @@ macro_rules! __impl_public_bitflags {
fn from_name(name) {
$(
- __bitflags_flag!({
+ $crate::__bitflags_flag!({
name: $Flag,
named: {
- __bitflags_expr_safe_attrs!(
+ $crate::__bitflags_expr_safe_attrs!(
$(#[$inner $($args)*])*
{
if name == $crate::__private::core::stringify!($Flag) {
@@ -268,7 +268,7 @@ macro_rules! __impl_public_bitflags {
}
/// Implement iterators on the public (user-facing) bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags_iter {
($BitFlags:ident: $T:ty, $PublicBitFlags:ident) => {
@@ -312,7 +312,7 @@ macro_rules! __impl_public_bitflags_iter {
}
/// Implement traits on the public (user-facing) bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags_ops {
($PublicBitFlags:ident) => {
@@ -321,7 +321,8 @@ macro_rules! __impl_public_bitflags_ops {
&self,
f: &mut $crate::__private::core::fmt::Formatter,
) -> $crate::__private::core::fmt::Result {
- $crate::__private::core::fmt::Binary::fmt(&self.0, f)
+ let inner = self.0;
+ $crate::__private::core::fmt::Binary::fmt(&inner, f)
}
}
@@ -330,7 +331,8 @@ macro_rules! __impl_public_bitflags_ops {
&self,
f: &mut $crate::__private::core::fmt::Formatter,
) -> $crate::__private::core::fmt::Result {
- $crate::__private::core::fmt::Octal::fmt(&self.0, f)
+ let inner = self.0;
+ $crate::__private::core::fmt::Octal::fmt(&inner, f)
}
}
@@ -339,7 +341,8 @@ macro_rules! __impl_public_bitflags_ops {
&self,
f: &mut $crate::__private::core::fmt::Formatter,
) -> $crate::__private::core::fmt::Result {
- $crate::__private::core::fmt::LowerHex::fmt(&self.0, f)
+ let inner = self.0;
+ $crate::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
@@ -348,7 +351,8 @@ macro_rules! __impl_public_bitflags_ops {
&self,
f: &mut $crate::__private::core::fmt::Formatter,
) -> $crate::__private::core::fmt::Result {
- $crate::__private::core::fmt::UpperHex::fmt(&self.0, f)
+ let inner = self.0;
+ $crate::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
@@ -468,7 +472,7 @@ macro_rules! __impl_public_bitflags_ops {
}
/// Implement constants on the public (user-facing) bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
#[doc(hidden)]
macro_rules! __impl_public_bitflags_consts {
(
@@ -481,7 +485,7 @@ macro_rules! __impl_public_bitflags_consts {
) => {
impl $PublicBitFlags {
$(
- __bitflags_flag!({
+ $crate::__bitflags_flag!({
name: $Flag,
named: {
$(#[$inner $($args)*])*
@@ -499,10 +503,10 @@ macro_rules! __impl_public_bitflags_consts {
impl $crate::Flags for $PublicBitFlags {
const FLAGS: &'static [$crate::Flag<$PublicBitFlags>] = &[
$(
- __bitflags_flag!({
+ $crate::__bitflags_flag!({
name: $Flag,
named: {
- __bitflags_expr_safe_attrs!(
+ $crate::__bitflags_expr_safe_attrs!(
$(#[$inner $($args)*])*
{
#[allow(
@@ -514,7 +518,7 @@ macro_rules! __impl_public_bitflags_consts {
)
},
unnamed: {
- __bitflags_expr_safe_attrs!(
+ $crate::__bitflags_expr_safe_attrs!(
$(#[$inner $($args)*])*
{
#[allow(
diff --git a/third_party/rust/bitflags/src/tests/all.rs b/third_party/rust/bitflags/src/tests/all.rs
new file mode 100644
index 0000000000..cceb93a469
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/all.rs
@@ -0,0 +1,23 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(1 | 1 << 1 | 1 << 2, TestFlags::all);
+
+ case(0, TestZero::all);
+
+ case(0, TestEmpty::all);
+
+ case(!0, TestExternal::all);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: T::Bits, inherent: impl FnOnce() -> T)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(expected, inherent().bits(), "T::all()");
+ assert_eq!(expected, T::all().bits(), "Flags::all()");
+}
diff --git a/third_party/rust/bitflags/src/tests/bits.rs b/third_party/rust/bitflags/src/tests/bits.rs
new file mode 100644
index 0000000000..678f153e36
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/bits.rs
@@ -0,0 +1,36 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, TestFlags::empty(), TestFlags::bits);
+
+ case(1, TestFlags::A, TestFlags::bits);
+ case(1 | 1 << 1 | 1 << 2, TestFlags::ABC, TestFlags::bits);
+
+ case(!0, TestFlags::from_bits_retain(u8::MAX), TestFlags::bits);
+ case(1 << 3, TestFlags::from_bits_retain(1 << 3), TestFlags::bits);
+
+ case(1 << 3, TestZero::from_bits_retain(1 << 3), TestZero::bits);
+
+ case(1 << 3, TestEmpty::from_bits_retain(1 << 3), TestEmpty::bits);
+
+ case(
+ 1 << 4 | 1 << 6,
+ TestExternal::from_bits_retain(1 << 4 | 1 << 6),
+ TestExternal::bits,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug>(
+ expected: T::Bits,
+ value: T,
+ inherent: impl FnOnce(&T) -> T::Bits,
+) where
+ T::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(expected, inherent(&value), "{:?}.bits()", value);
+ assert_eq!(expected, Flags::bits(&value), "Flags::bits({:?})", value);
+}
diff --git a/third_party/rust/bitflags/src/tests/complement.rs b/third_party/rust/bitflags/src/tests/complement.rs
new file mode 100644
index 0000000000..ac7a421af0
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/complement.rs
@@ -0,0 +1,53 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, TestFlags::all(), TestFlags::complement);
+ case(0, TestFlags::from_bits_retain(!0), TestFlags::complement);
+
+ case(1 | 1 << 1, TestFlags::C, TestFlags::complement);
+ case(
+ 1 | 1 << 1,
+ TestFlags::C | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::complement,
+ );
+
+ case(
+ 1 | 1 << 1 | 1 << 2,
+ TestFlags::empty(),
+ TestFlags::complement,
+ );
+ case(
+ 1 | 1 << 1 | 1 << 2,
+ TestFlags::from_bits_retain(1 << 3),
+ TestFlags::complement,
+ );
+
+ case(0, TestZero::empty(), TestZero::complement);
+
+ case(0, TestEmpty::empty(), TestEmpty::complement);
+
+ case(1 << 2, TestOverlapping::AB, TestOverlapping::complement);
+
+ case(!0, TestExternal::empty(), TestExternal::complement);
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::Not<Output = T> + Copy>(
+ expected: T::Bits,
+ value: T,
+ inherent: impl FnOnce(T) -> T,
+) where
+ T::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(expected, inherent(value).bits(), "{:?}.complement()", value);
+ assert_eq!(
+ expected,
+ Flags::complement(value).bits(),
+ "Flags::complement({:?})",
+ value
+ );
+ assert_eq!(expected, (!value).bits(), "!{:?}", value);
+}
diff --git a/third_party/rust/bitflags/src/tests/contains.rs b/third_party/rust/bitflags/src/tests/contains.rs
new file mode 100644
index 0000000000..12428ddcb0
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/contains.rs
@@ -0,0 +1,108 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::empty(), true),
+ (TestFlags::A, false),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ ],
+ TestFlags::contains,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::empty(), true),
+ (TestFlags::A, true),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::ABC, false),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ (TestFlags::from_bits_retain(1 | (1 << 3)), false),
+ ],
+ TestFlags::contains,
+ );
+
+ case(
+ TestFlags::ABC,
+ &[
+ (TestFlags::empty(), true),
+ (TestFlags::A, true),
+ (TestFlags::B, true),
+ (TestFlags::C, true),
+ (TestFlags::ABC, true),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ ],
+ TestFlags::contains,
+ );
+
+ case(
+ TestFlags::from_bits_retain(1 << 3),
+ &[
+ (TestFlags::empty(), true),
+ (TestFlags::A, false),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::from_bits_retain(1 << 3), true),
+ ],
+ TestFlags::contains,
+ );
+
+ case(
+ TestZero::ZERO,
+ &[(TestZero::ZERO, true)],
+ TestZero::contains,
+ );
+
+ case(
+ TestOverlapping::AB,
+ &[
+ (TestOverlapping::AB, true),
+ (TestOverlapping::BC, false),
+ (TestOverlapping::from_bits_retain(1 << 1), true),
+ ],
+ TestOverlapping::contains,
+ );
+
+ case(
+ TestExternal::all(),
+ &[
+ (TestExternal::A, true),
+ (TestExternal::B, true),
+ (TestExternal::C, true),
+ (TestExternal::from_bits_retain(1 << 5 | 1 << 7), true),
+ ],
+ TestExternal::contains,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+ value: T,
+ inputs: &[(T, bool)],
+ mut inherent: impl FnMut(&T, T) -> bool,
+) {
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(&value, *input),
+ "{:?}.contains({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::contains(&value, *input),
+ "Flags::contains({:?}, {:?})",
+ value,
+ input
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/difference.rs b/third_party/rust/bitflags/src/tests/difference.rs
new file mode 100644
index 0000000000..6ce9c0bf19
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/difference.rs
@@ -0,0 +1,92 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::A | TestFlags::B,
+ &[
+ (TestFlags::A, 1 << 1),
+ (TestFlags::B, 1),
+ (TestFlags::from_bits_retain(1 << 3), 1 | 1 << 1),
+ ],
+ TestFlags::difference,
+ );
+
+ case(
+ TestFlags::from_bits_retain(1 | 1 << 3),
+ &[
+ (TestFlags::A, 1 << 3),
+ (TestFlags::from_bits_retain(1 << 3), 1),
+ ],
+ TestFlags::difference,
+ );
+
+ case(
+ TestExternal::from_bits_retain(!0),
+ &[(TestExternal::A, 0b1111_1110)],
+ TestExternal::difference,
+ );
+
+ assert_eq!(
+ 0b1111_1110,
+ (TestExternal::from_bits_retain(!0) & !TestExternal::A).bits()
+ );
+
+ assert_eq!(
+ 0b1111_1110,
+ (TestFlags::from_bits_retain(!0).difference(TestFlags::A)).bits()
+ );
+
+ // The `!` operator unsets bits that don't correspond to known flags
+ assert_eq!(
+ 1 << 1 | 1 << 2,
+ (TestFlags::from_bits_retain(!0) & !TestFlags::A).bits()
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::Sub<Output = T> + std::ops::SubAssign + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent: impl FnMut(T, T) -> T,
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(value, *input).bits(),
+ "{:?}.difference({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::difference(value, *input).bits(),
+ "Flags::difference({:?}, {:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ (value - *input).bits(),
+ "{:?} - {:?}",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ value -= *input;
+ value
+ }
+ .bits(),
+ "{:?} -= {:?}",
+ value,
+ input,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/empty.rs b/third_party/rust/bitflags/src/tests/empty.rs
new file mode 100644
index 0000000000..57fb1c7cf1
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/empty.rs
@@ -0,0 +1,23 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, TestFlags::empty);
+
+ case(0, TestZero::empty);
+
+ case(0, TestEmpty::empty);
+
+ case(0, TestExternal::empty);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: T::Bits, inherent: impl FnOnce() -> T)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(expected, inherent().bits(), "T::empty()");
+ assert_eq!(expected, T::empty().bits(), "Flags::empty()");
+}
diff --git a/third_party/rust/bitflags/src/tests/eq.rs b/third_party/rust/bitflags/src/tests/eq.rs
new file mode 100644
index 0000000000..9779af7629
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/eq.rs
@@ -0,0 +1,10 @@
+use super::*;
+
+#[test]
+fn cases() {
+ assert_eq!(TestFlags::empty(), TestFlags::empty());
+ assert_eq!(TestFlags::all(), TestFlags::all());
+
+ assert!(TestFlags::from_bits_retain(1) < TestFlags::from_bits_retain(2));
+ assert!(TestFlags::from_bits_retain(2) > TestFlags::from_bits_retain(1));
+}
diff --git a/third_party/rust/bitflags/src/tests/extend.rs b/third_party/rust/bitflags/src/tests/extend.rs
new file mode 100644
index 0000000000..869dc17fc8
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/extend.rs
@@ -0,0 +1,42 @@
+use super::*;
+
+#[test]
+fn cases() {
+ let mut flags = TestFlags::empty();
+
+ flags.extend(TestFlags::A);
+
+ assert_eq!(TestFlags::A, flags);
+
+ flags.extend(TestFlags::A | TestFlags::B | TestFlags::C);
+
+ assert_eq!(TestFlags::ABC, flags);
+
+ flags.extend(TestFlags::from_bits_retain(1 << 5));
+
+ assert_eq!(TestFlags::ABC | TestFlags::from_bits_retain(1 << 5), flags);
+}
+
+mod external {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ let mut flags = TestExternal::empty();
+
+ flags.extend(TestExternal::A);
+
+ assert_eq!(TestExternal::A, flags);
+
+ flags.extend(TestExternal::A | TestExternal::B | TestExternal::C);
+
+ assert_eq!(TestExternal::ABC, flags);
+
+ flags.extend(TestExternal::from_bits_retain(1 << 5));
+
+ assert_eq!(
+ TestExternal::ABC | TestExternal::from_bits_retain(1 << 5),
+ flags
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/flags.rs b/third_party/rust/bitflags/src/tests/flags.rs
new file mode 100644
index 0000000000..7a625b312c
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/flags.rs
@@ -0,0 +1,46 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ let flags = TestFlags::FLAGS
+ .iter()
+ .map(|flag| (flag.name(), flag.value().bits()))
+ .collect::<Vec<_>>();
+
+ assert_eq!(
+ vec![
+ ("A", 1u8),
+ ("B", 1 << 1),
+ ("C", 1 << 2),
+ ("ABC", 1 | 1 << 1 | 1 << 2),
+ ],
+ flags,
+ );
+
+ assert_eq!(0, TestEmpty::FLAGS.iter().count());
+}
+
+mod external {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ let flags = TestExternal::FLAGS
+ .iter()
+ .map(|flag| (flag.name(), flag.value().bits()))
+ .collect::<Vec<_>>();
+
+ assert_eq!(
+ vec![
+ ("A", 1u8),
+ ("B", 1 << 1),
+ ("C", 1 << 2),
+ ("ABC", 1 | 1 << 1 | 1 << 2),
+ ("", !0),
+ ],
+ flags,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/fmt.rs b/third_party/rust/bitflags/src/tests/fmt.rs
new file mode 100644
index 0000000000..ed4571877d
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/fmt.rs
@@ -0,0 +1,97 @@
+use super::*;
+
+#[test]
+fn cases() {
+ case(TestFlags::empty(), "TestFlags(0x0)", "0", "0", "0", "0");
+ case(TestFlags::A, "TestFlags(A)", "1", "1", "1", "1");
+ case(
+ TestFlags::all(),
+ "TestFlags(A | B | C)",
+ "7",
+ "7",
+ "7",
+ "111",
+ );
+ case(
+ TestFlags::from_bits_retain(1 << 3),
+ "TestFlags(0x8)",
+ "8",
+ "8",
+ "10",
+ "1000",
+ );
+ case(
+ TestFlags::A | TestFlags::from_bits_retain(1 << 3),
+ "TestFlags(A | 0x8)",
+ "9",
+ "9",
+ "11",
+ "1001",
+ );
+
+ case(TestZero::ZERO, "TestZero(0x0)", "0", "0", "0", "0");
+ case(
+ TestZero::ZERO | TestZero::from_bits_retain(1),
+ "TestZero(0x1)",
+ "1",
+ "1",
+ "1",
+ "1",
+ );
+
+ case(TestZeroOne::ONE, "TestZeroOne(ONE)", "1", "1", "1", "1");
+
+ case(
+ TestOverlapping::from_bits_retain(1 << 1),
+ "TestOverlapping(0x2)",
+ "2",
+ "2",
+ "2",
+ "10",
+ );
+
+ case(
+ TestExternal::from_bits_retain(1 | 1 << 1 | 1 << 3),
+ "TestExternal(A | B | 0x8)",
+ "B",
+ "b",
+ "13",
+ "1011",
+ );
+
+ case(
+ TestExternal::all(),
+ "TestExternal(A | B | C | 0xf8)",
+ "FF",
+ "ff",
+ "377",
+ "11111111",
+ );
+
+ case(
+ TestExternalFull::all(),
+ "TestExternalFull(0xff)",
+ "FF",
+ "ff",
+ "377",
+ "11111111",
+ );
+}
+
+#[track_caller]
+fn case<
+ T: std::fmt::Debug + std::fmt::UpperHex + std::fmt::LowerHex + std::fmt::Octal + std::fmt::Binary,
+>(
+ value: T,
+ debug: &str,
+ uhex: &str,
+ lhex: &str,
+ oct: &str,
+ bin: &str,
+) {
+ assert_eq!(debug, format!("{:?}", value));
+ assert_eq!(uhex, format!("{:X}", value));
+ assert_eq!(lhex, format!("{:x}", value));
+ assert_eq!(oct, format!("{:o}", value));
+ assert_eq!(bin, format!("{:b}", value));
+}
diff --git a/third_party/rust/bitflags/src/tests/from_bits.rs b/third_party/rust/bitflags/src/tests/from_bits.rs
new file mode 100644
index 0000000000..dada9aff82
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/from_bits.rs
@@ -0,0 +1,45 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(Some(0), 0, TestFlags::from_bits);
+ case(Some(1), 1, TestFlags::from_bits);
+ case(
+ Some(1 | 1 << 1 | 1 << 2),
+ 1 | 1 << 1 | 1 << 2,
+ TestFlags::from_bits,
+ );
+
+ case(None, 1 << 3, TestFlags::from_bits);
+ case(None, 1 | 1 << 3, TestFlags::from_bits);
+
+ case(Some(1 | 1 << 1), 1 | 1 << 1, TestOverlapping::from_bits);
+
+ case(Some(1 << 1), 1 << 1, TestOverlapping::from_bits);
+
+ case(Some(1 << 5), 1 << 5, TestExternal::from_bits);
+}
+
+#[track_caller]
+fn case<T: Flags>(
+ expected: Option<T::Bits>,
+ input: T::Bits,
+ inherent: impl FnOnce(T::Bits) -> Option<T>,
+) where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(
+ expected,
+ inherent(input).map(|f| f.bits()),
+ "T::from_bits({:?})",
+ input
+ );
+ assert_eq!(
+ expected,
+ T::from_bits(input).map(|f| f.bits()),
+ "Flags::from_bits({:?})",
+ input
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/from_bits_retain.rs b/third_party/rust/bitflags/src/tests/from_bits_retain.rs
new file mode 100644
index 0000000000..1ae28a663f
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/from_bits_retain.rs
@@ -0,0 +1,38 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, TestFlags::from_bits_retain);
+ case(1, TestFlags::from_bits_retain);
+ case(1 | 1 << 1 | 1 << 2, TestFlags::from_bits_retain);
+
+ case(1 << 3, TestFlags::from_bits_retain);
+ case(1 | 1 << 3, TestFlags::from_bits_retain);
+
+ case(1 | 1 << 1, TestOverlapping::from_bits_retain);
+
+ case(1 << 1, TestOverlapping::from_bits_retain);
+
+ case(1 << 5, TestExternal::from_bits_retain);
+}
+
+#[track_caller]
+fn case<T: Flags>(input: T::Bits, inherent: impl FnOnce(T::Bits) -> T)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(
+ input,
+ inherent(input).bits(),
+ "T::from_bits_retain({:?})",
+ input
+ );
+ assert_eq!(
+ input,
+ T::from_bits_retain(input).bits(),
+ "Flags::from_bits_retain({:?})",
+ input
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/from_bits_truncate.rs b/third_party/rust/bitflags/src/tests/from_bits_truncate.rs
new file mode 100644
index 0000000000..e4f3e537c4
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/from_bits_truncate.rs
@@ -0,0 +1,42 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(0, 0, TestFlags::from_bits_truncate);
+ case(1, 1, TestFlags::from_bits_truncate);
+ case(
+ 1 | 1 << 1 | 1 << 2,
+ 1 | 1 << 1 | 1 << 2,
+ TestFlags::from_bits_truncate,
+ );
+
+ case(0, 1 << 3, TestFlags::from_bits_truncate);
+ case(1, 1 | 1 << 3, TestFlags::from_bits_truncate);
+
+ case(1 | 1 << 1, 1 | 1 << 1, TestOverlapping::from_bits_truncate);
+
+ case(1 << 1, 1 << 1, TestOverlapping::from_bits_truncate);
+
+ case(1 << 5, 1 << 5, TestExternal::from_bits_truncate);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: T::Bits, input: T::Bits, inherent: impl FnOnce(T::Bits) -> T)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(
+ expected,
+ inherent(input).bits(),
+ "T::from_bits_truncate({:?})",
+ input
+ );
+ assert_eq!(
+ expected,
+ T::from_bits_truncate(input).bits(),
+ "Flags::from_bits_truncate({:?})",
+ input
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/from_name.rs b/third_party/rust/bitflags/src/tests/from_name.rs
new file mode 100644
index 0000000000..1d9a4e48b6
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/from_name.rs
@@ -0,0 +1,42 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(Some(1), "A", TestFlags::from_name);
+ case(Some(1 << 1), "B", TestFlags::from_name);
+ case(Some(1 | 1 << 1 | 1 << 2), "ABC", TestFlags::from_name);
+
+ case(None, "", TestFlags::from_name);
+ case(None, "a", TestFlags::from_name);
+ case(None, "0x1", TestFlags::from_name);
+ case(None, "A | B", TestFlags::from_name);
+
+ case(Some(0), "ZERO", TestZero::from_name);
+
+ case(Some(2), "二", TestUnicode::from_name);
+
+ case(None, "_", TestExternal::from_name);
+
+ case(None, "", TestExternal::from_name);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: Option<T::Bits>, input: &str, inherent: impl FnOnce(&str) -> Option<T>)
+where
+ <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+ assert_eq!(
+ expected,
+ inherent(input).map(|f| f.bits()),
+ "T::from_name({:?})",
+ input
+ );
+ assert_eq!(
+ expected,
+ T::from_name(input).map(|f| f.bits()),
+ "Flags::from_name({:?})",
+ input
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/insert.rs b/third_party/rust/bitflags/src/tests/insert.rs
new file mode 100644
index 0000000000..b18cd17235
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/insert.rs
@@ -0,0 +1,91 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::A, 1),
+ (TestFlags::A | TestFlags::B, 1 | 1 << 1),
+ (TestFlags::empty(), 0),
+ (TestFlags::from_bits_retain(1 << 3), 1 << 3),
+ ],
+ TestFlags::insert,
+ TestFlags::set,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::A, 1),
+ (TestFlags::empty(), 1),
+ (TestFlags::B, 1 | 1 << 1),
+ ],
+ TestFlags::insert,
+ TestFlags::set,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent_insert: impl FnMut(&mut T, T),
+ mut inherent_set: impl FnMut(&mut T, T, bool),
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_insert(&mut value, *input);
+ value
+ }
+ .bits(),
+ "{:?}.insert({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::insert(&mut value, *input);
+ value
+ }
+ .bits(),
+ "Flags::insert({:?}, {:?})",
+ value,
+ input
+ );
+
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_set(&mut value, *input, true);
+ value
+ }
+ .bits(),
+ "{:?}.set({:?}, true)",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::set(&mut value, *input, true);
+ value
+ }
+ .bits(),
+ "Flags::set({:?}, {:?}, true)",
+ value,
+ input
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/intersection.rs b/third_party/rust/bitflags/src/tests/intersection.rs
new file mode 100644
index 0000000000..10a8ae9fb6
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/intersection.rs
@@ -0,0 +1,79 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[(TestFlags::empty(), 0), (TestFlags::all(), 0)],
+ TestFlags::intersection,
+ );
+
+ case(
+ TestFlags::all(),
+ &[
+ (TestFlags::all(), 1 | 1 << 1 | 1 << 2),
+ (TestFlags::A, 1),
+ (TestFlags::from_bits_retain(1 << 3), 0),
+ ],
+ TestFlags::intersection,
+ );
+
+ case(
+ TestFlags::from_bits_retain(1 << 3),
+ &[(TestFlags::from_bits_retain(1 << 3), 1 << 3)],
+ TestFlags::intersection,
+ );
+
+ case(
+ TestOverlapping::AB,
+ &[(TestOverlapping::BC, 1 << 1)],
+ TestOverlapping::intersection,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::BitAnd<Output = T> + std::ops::BitAndAssign + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent: impl FnMut(T, T) -> T,
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(value, *input).bits(),
+ "{:?}.intersection({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::intersection(value, *input).bits(),
+ "Flags::intersection({:?}, {:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ (value & *input).bits(),
+ "{:?} & {:?}",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ value &= *input;
+ value
+ }
+ .bits(),
+ "{:?} &= {:?}",
+ value,
+ input,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/intersects.rs b/third_party/rust/bitflags/src/tests/intersects.rs
new file mode 100644
index 0000000000..fe907981a2
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/intersects.rs
@@ -0,0 +1,91 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::empty(), false),
+ (TestFlags::A, false),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ ],
+ TestFlags::intersects,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::empty(), false),
+ (TestFlags::A, true),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::ABC, true),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ (TestFlags::from_bits_retain(1 | (1 << 3)), true),
+ ],
+ TestFlags::intersects,
+ );
+
+ case(
+ TestFlags::ABC,
+ &[
+ (TestFlags::empty(), false),
+ (TestFlags::A, true),
+ (TestFlags::B, true),
+ (TestFlags::C, true),
+ (TestFlags::ABC, true),
+ (TestFlags::from_bits_retain(1 << 3), false),
+ ],
+ TestFlags::intersects,
+ );
+
+ case(
+ TestFlags::from_bits_retain(1 << 3),
+ &[
+ (TestFlags::empty(), false),
+ (TestFlags::A, false),
+ (TestFlags::B, false),
+ (TestFlags::C, false),
+ (TestFlags::from_bits_retain(1 << 3), true),
+ ],
+ TestFlags::intersects,
+ );
+
+ case(
+ TestOverlapping::AB,
+ &[
+ (TestOverlapping::AB, true),
+ (TestOverlapping::BC, true),
+ (TestOverlapping::from_bits_retain(1 << 1), true),
+ ],
+ TestOverlapping::intersects,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+ value: T,
+ inputs: &[(T, bool)],
+ mut inherent: impl FnMut(&T, T) -> bool,
+) {
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(&value, *input),
+ "{:?}.intersects({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::intersects(&value, *input),
+ "Flags::intersects({:?}, {:?})",
+ value,
+ input
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/is_all.rs b/third_party/rust/bitflags/src/tests/is_all.rs
new file mode 100644
index 0000000000..382a458f61
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/is_all.rs
@@ -0,0 +1,32 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(false, TestFlags::empty(), TestFlags::is_all);
+ case(false, TestFlags::A, TestFlags::is_all);
+
+ case(true, TestFlags::ABC, TestFlags::is_all);
+
+ case(
+ true,
+ TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::is_all,
+ );
+
+ case(true, TestZero::empty(), TestZero::is_all);
+
+ case(true, TestEmpty::empty(), TestEmpty::is_all);
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug>(expected: bool, value: T, inherent: impl FnOnce(&T) -> bool) {
+ assert_eq!(expected, inherent(&value), "{:?}.is_all()", value);
+ assert_eq!(
+ expected,
+ Flags::is_all(&value),
+ "Flags::is_all({:?})",
+ value
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/is_empty.rs b/third_party/rust/bitflags/src/tests/is_empty.rs
new file mode 100644
index 0000000000..92165f18e3
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/is_empty.rs
@@ -0,0 +1,31 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(true, TestFlags::empty(), TestFlags::is_empty);
+
+ case(false, TestFlags::A, TestFlags::is_empty);
+ case(false, TestFlags::ABC, TestFlags::is_empty);
+ case(
+ false,
+ TestFlags::from_bits_retain(1 << 3),
+ TestFlags::is_empty,
+ );
+
+ case(true, TestZero::empty(), TestZero::is_empty);
+
+ case(true, TestEmpty::empty(), TestEmpty::is_empty);
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug>(expected: bool, value: T, inherent: impl FnOnce(&T) -> bool) {
+ assert_eq!(expected, inherent(&value), "{:?}.is_empty()", value);
+ assert_eq!(
+ expected,
+ Flags::is_empty(&value),
+ "Flags::is_empty({:?})",
+ value
+ );
+}
diff --git a/third_party/rust/bitflags/src/tests/iter.rs b/third_party/rust/bitflags/src/tests/iter.rs
new file mode 100644
index 0000000000..54b1d27d4c
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/iter.rs
@@ -0,0 +1,209 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip() {
+ for a in 0u8..=255 {
+ for b in 0u8..=255 {
+ let f = TestFlags::from_bits_retain(a | b);
+
+ assert_eq!(f, f.iter().collect::<TestFlags>());
+ assert_eq!(
+ TestFlags::from_bits_truncate(f.bits()),
+ f.iter_names().map(|(_, f)| f).collect::<TestFlags>()
+ );
+
+ let f = TestExternal::from_bits_retain(a | b);
+
+ assert_eq!(f, f.iter().collect::<TestExternal>());
+ }
+ }
+}
+
+mod collect {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ assert_eq!(0, [].into_iter().collect::<TestFlags>().bits());
+
+ assert_eq!(1, [TestFlags::A,].into_iter().collect::<TestFlags>().bits());
+
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ [TestFlags::A, TestFlags::B | TestFlags::C,]
+ .into_iter()
+ .collect::<TestFlags>()
+ .bits()
+ );
+
+ assert_eq!(
+ 1 | 1 << 3,
+ [
+ TestFlags::from_bits_retain(1 << 3),
+ TestFlags::empty(),
+ TestFlags::A,
+ ]
+ .into_iter()
+ .collect::<TestFlags>()
+ .bits()
+ );
+
+ assert_eq!(
+ 1 << 5 | 1 << 7,
+ [
+ TestExternal::empty(),
+ TestExternal::from_bits_retain(1 << 5),
+ TestExternal::from_bits_retain(1 << 7),
+ ]
+ .into_iter()
+ .collect::<TestExternal>()
+ .bits()
+ );
+ }
+}
+
+mod iter {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ case(&[], TestFlags::empty(), TestFlags::iter);
+
+ case(&[1], TestFlags::A, TestFlags::iter);
+ case(&[1, 1 << 1], TestFlags::A | TestFlags::B, TestFlags::iter);
+ case(
+ &[1, 1 << 1, 1 << 3],
+ TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter,
+ );
+
+ case(&[1, 1 << 1, 1 << 2], TestFlags::ABC, TestFlags::iter);
+ case(
+ &[1, 1 << 1, 1 << 2, 1 << 3],
+ TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter,
+ );
+
+ case(
+ &[1 | 1 << 1 | 1 << 2],
+ TestFlagsInvert::ABC,
+ TestFlagsInvert::iter,
+ );
+
+ case(&[], TestZero::ZERO, TestZero::iter);
+
+ case(
+ &[1, 1 << 1, 1 << 2, 0b1111_1000],
+ TestExternal::all(),
+ TestExternal::iter,
+ );
+ }
+
+ #[track_caller]
+ fn case<T: Flags + std::fmt::Debug + IntoIterator<Item = T> + Copy>(
+ expected: &[T::Bits],
+ value: T,
+ inherent: impl FnOnce(&T) -> crate::iter::Iter<T>,
+ ) where
+ T::Bits: std::fmt::Debug + PartialEq,
+ {
+ assert_eq!(
+ expected,
+ inherent(&value).map(|f| f.bits()).collect::<Vec<_>>(),
+ "{:?}.iter()",
+ value
+ );
+ assert_eq!(
+ expected,
+ Flags::iter(&value).map(|f| f.bits()).collect::<Vec<_>>(),
+ "Flags::iter({:?})",
+ value
+ );
+ assert_eq!(
+ expected,
+ value.into_iter().map(|f| f.bits()).collect::<Vec<_>>(),
+ "{:?}.into_iter()",
+ value
+ );
+ }
+}
+
+mod iter_names {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ case(&[], TestFlags::empty(), TestFlags::iter_names);
+
+ case(&[("A", 1)], TestFlags::A, TestFlags::iter_names);
+ case(
+ &[("A", 1), ("B", 1 << 1)],
+ TestFlags::A | TestFlags::B,
+ TestFlags::iter_names,
+ );
+ case(
+ &[("A", 1), ("B", 1 << 1)],
+ TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter_names,
+ );
+
+ case(
+ &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
+ TestFlags::ABC,
+ TestFlags::iter_names,
+ );
+ case(
+ &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
+ TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter_names,
+ );
+
+ case(
+ &[("ABC", 1 | 1 << 1 | 1 << 2)],
+ TestFlagsInvert::ABC,
+ TestFlagsInvert::iter_names,
+ );
+
+ case(&[], TestZero::ZERO, TestZero::iter_names);
+
+ case(
+ &[("A", 1)],
+ TestOverlappingFull::A,
+ TestOverlappingFull::iter_names,
+ );
+ case(
+ &[("A", 1), ("D", 1 << 1)],
+ TestOverlappingFull::A | TestOverlappingFull::D,
+ TestOverlappingFull::iter_names,
+ );
+ }
+
+ #[track_caller]
+ fn case<T: Flags + std::fmt::Debug>(
+ expected: &[(&'static str, T::Bits)],
+ value: T,
+ inherent: impl FnOnce(&T) -> crate::iter::IterNames<T>,
+ ) where
+ T::Bits: std::fmt::Debug + PartialEq,
+ {
+ assert_eq!(
+ expected,
+ inherent(&value)
+ .map(|(n, f)| (n, f.bits()))
+ .collect::<Vec<_>>(),
+ "{:?}.iter_names()",
+ value
+ );
+ assert_eq!(
+ expected,
+ Flags::iter_names(&value)
+ .map(|(n, f)| (n, f.bits()))
+ .collect::<Vec<_>>(),
+ "Flags::iter_names({:?})",
+ value
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/parser.rs b/third_party/rust/bitflags/src/tests/parser.rs
new file mode 100644
index 0000000000..fb27225ece
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/parser.rs
@@ -0,0 +1,332 @@
+use super::*;
+
+use crate::{parser::*, Flags};
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip() {
+ let mut s = String::new();
+
+ for a in 0u8..=255 {
+ for b in 0u8..=255 {
+ let f = TestFlags::from_bits_retain(a | b);
+
+ s.clear();
+ to_writer(&f, &mut s).unwrap();
+
+ assert_eq!(f, from_str::<TestFlags>(&s).unwrap());
+ }
+ }
+}
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip_truncate() {
+ let mut s = String::new();
+
+ for a in 0u8..=255 {
+ for b in 0u8..=255 {
+ let f = TestFlags::from_bits_retain(a | b);
+
+ s.clear();
+ to_writer_truncate(&f, &mut s).unwrap();
+
+ assert_eq!(
+ TestFlags::from_bits_truncate(f.bits()),
+ from_str_truncate::<TestFlags>(&s).unwrap()
+ );
+ }
+ }
+}
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip_strict() {
+ let mut s = String::new();
+
+ for a in 0u8..=255 {
+ for b in 0u8..=255 {
+ let f = TestFlags::from_bits_retain(a | b);
+
+ s.clear();
+ to_writer_strict(&f, &mut s).unwrap();
+
+ let mut strict = TestFlags::empty();
+ for (_, flag) in f.iter_names() {
+ strict |= flag;
+ }
+ let f = strict;
+
+ if let Ok(s) = from_str_strict::<TestFlags>(&s) {
+ assert_eq!(f, s);
+ }
+ }
+ }
+}
+
+mod from_str {
+ use super::*;
+
+ #[test]
+ fn valid() {
+ assert_eq!(0, from_str::<TestFlags>("").unwrap().bits());
+
+ assert_eq!(1, from_str::<TestFlags>("A").unwrap().bits());
+ assert_eq!(1, from_str::<TestFlags>(" A ").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str::<TestFlags>("A | B | C").unwrap().bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str::<TestFlags>("A\n|\tB\r\n| C ").unwrap().bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str::<TestFlags>("A|B|C").unwrap().bits()
+ );
+
+ assert_eq!(1 << 3, from_str::<TestFlags>("0x8").unwrap().bits());
+ assert_eq!(1 | 1 << 3, from_str::<TestFlags>("A | 0x8").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 3,
+ from_str::<TestFlags>("0x1 | 0x8 | B").unwrap().bits()
+ );
+
+ assert_eq!(
+ 1 | 1 << 1,
+ from_str::<TestUnicode>("一 | 二").unwrap().bits()
+ );
+ }
+
+ #[test]
+ fn invalid() {
+ assert!(from_str::<TestFlags>("a")
+ .unwrap_err()
+ .to_string()
+ .starts_with("unrecognized named flag"));
+ assert!(from_str::<TestFlags>("A & B")
+ .unwrap_err()
+ .to_string()
+ .starts_with("unrecognized named flag"));
+
+ assert!(from_str::<TestFlags>("0xg")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ assert!(from_str::<TestFlags>("0xffffffffffff")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ }
+}
+
+mod to_writer {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ assert_eq!("", write(TestFlags::empty()));
+ assert_eq!("A", write(TestFlags::A));
+ assert_eq!("A | B | C", write(TestFlags::all()));
+ assert_eq!("0x8", write(TestFlags::from_bits_retain(1 << 3)));
+ assert_eq!(
+ "A | 0x8",
+ write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
+ );
+
+ assert_eq!("", write(TestZero::ZERO));
+
+ assert_eq!("ABC", write(TestFlagsInvert::all()));
+
+ assert_eq!("0x1", write(TestOverlapping::from_bits_retain(1)));
+
+ assert_eq!("A", write(TestOverlappingFull::C));
+ assert_eq!(
+ "A | D",
+ write(TestOverlappingFull::C | TestOverlappingFull::D)
+ );
+ }
+
+ fn write<F: Flags>(value: F) -> String
+ where
+ F::Bits: crate::parser::WriteHex,
+ {
+ let mut s = String::new();
+
+ to_writer(&value, &mut s).unwrap();
+ s
+ }
+}
+
+mod from_str_truncate {
+ use super::*;
+
+ #[test]
+ fn valid() {
+ assert_eq!(0, from_str_truncate::<TestFlags>("").unwrap().bits());
+
+ assert_eq!(1, from_str_truncate::<TestFlags>("A").unwrap().bits());
+ assert_eq!(1, from_str_truncate::<TestFlags>(" A ").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_truncate::<TestFlags>("A | B | C").unwrap().bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_truncate::<TestFlags>("A\n|\tB\r\n| C ")
+ .unwrap()
+ .bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_truncate::<TestFlags>("A|B|C").unwrap().bits()
+ );
+
+ assert_eq!(0, from_str_truncate::<TestFlags>("0x8").unwrap().bits());
+ assert_eq!(1, from_str_truncate::<TestFlags>("A | 0x8").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1,
+ from_str_truncate::<TestFlags>("0x1 | 0x8 | B")
+ .unwrap()
+ .bits()
+ );
+
+ assert_eq!(
+ 1 | 1 << 1,
+ from_str_truncate::<TestUnicode>("一 | 二").unwrap().bits()
+ );
+ }
+}
+
+mod to_writer_truncate {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ assert_eq!("", write(TestFlags::empty()));
+ assert_eq!("A", write(TestFlags::A));
+ assert_eq!("A | B | C", write(TestFlags::all()));
+ assert_eq!("", write(TestFlags::from_bits_retain(1 << 3)));
+ assert_eq!(
+ "A",
+ write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
+ );
+
+ assert_eq!("", write(TestZero::ZERO));
+
+ assert_eq!("ABC", write(TestFlagsInvert::all()));
+
+ assert_eq!("0x1", write(TestOverlapping::from_bits_retain(1)));
+
+ assert_eq!("A", write(TestOverlappingFull::C));
+ assert_eq!(
+ "A | D",
+ write(TestOverlappingFull::C | TestOverlappingFull::D)
+ );
+ }
+
+ fn write<F: Flags>(value: F) -> String
+ where
+ F::Bits: crate::parser::WriteHex,
+ {
+ let mut s = String::new();
+
+ to_writer_truncate(&value, &mut s).unwrap();
+ s
+ }
+}
+
+mod from_str_strict {
+ use super::*;
+
+ #[test]
+ fn valid() {
+ assert_eq!(0, from_str_strict::<TestFlags>("").unwrap().bits());
+
+ assert_eq!(1, from_str_strict::<TestFlags>("A").unwrap().bits());
+ assert_eq!(1, from_str_strict::<TestFlags>(" A ").unwrap().bits());
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_strict::<TestFlags>("A | B | C").unwrap().bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_strict::<TestFlags>("A\n|\tB\r\n| C ")
+ .unwrap()
+ .bits()
+ );
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ from_str_strict::<TestFlags>("A|B|C").unwrap().bits()
+ );
+
+ assert_eq!(
+ 1 | 1 << 1,
+ from_str_strict::<TestUnicode>("一 | 二").unwrap().bits()
+ );
+ }
+
+ #[test]
+ fn invalid() {
+ assert!(from_str_strict::<TestFlags>("a")
+ .unwrap_err()
+ .to_string()
+ .starts_with("unrecognized named flag"));
+ assert!(from_str_strict::<TestFlags>("A & B")
+ .unwrap_err()
+ .to_string()
+ .starts_with("unrecognized named flag"));
+
+ assert!(from_str_strict::<TestFlags>("0x1")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ assert!(from_str_strict::<TestFlags>("0xg")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ assert!(from_str_strict::<TestFlags>("0xffffffffffff")
+ .unwrap_err()
+ .to_string()
+ .starts_with("invalid hex flag"));
+ }
+}
+
+mod to_writer_strict {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ assert_eq!("", write(TestFlags::empty()));
+ assert_eq!("A", write(TestFlags::A));
+ assert_eq!("A | B | C", write(TestFlags::all()));
+ assert_eq!("", write(TestFlags::from_bits_retain(1 << 3)));
+ assert_eq!(
+ "A",
+ write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
+ );
+
+ assert_eq!("", write(TestZero::ZERO));
+
+ assert_eq!("ABC", write(TestFlagsInvert::all()));
+
+ assert_eq!("", write(TestOverlapping::from_bits_retain(1)));
+
+ assert_eq!("A", write(TestOverlappingFull::C));
+ assert_eq!(
+ "A | D",
+ write(TestOverlappingFull::C | TestOverlappingFull::D)
+ );
+ }
+
+ fn write<F: Flags>(value: F) -> String
+ where
+ F::Bits: crate::parser::WriteHex,
+ {
+ let mut s = String::new();
+
+ to_writer_strict(&value, &mut s).unwrap();
+ s
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/remove.rs b/third_party/rust/bitflags/src/tests/remove.rs
new file mode 100644
index 0000000000..574b1edbf2
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/remove.rs
@@ -0,0 +1,100 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::A, 0),
+ (TestFlags::empty(), 0),
+ (TestFlags::from_bits_retain(1 << 3), 0),
+ ],
+ TestFlags::remove,
+ TestFlags::set,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::A, 0),
+ (TestFlags::empty(), 1),
+ (TestFlags::B, 1),
+ ],
+ TestFlags::remove,
+ TestFlags::set,
+ );
+
+ case(
+ TestFlags::ABC,
+ &[
+ (TestFlags::A, 1 << 1 | 1 << 2),
+ (TestFlags::A | TestFlags::C, 1 << 1),
+ ],
+ TestFlags::remove,
+ TestFlags::set,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent_remove: impl FnMut(&mut T, T),
+ mut inherent_set: impl FnMut(&mut T, T, bool),
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_remove(&mut value, *input);
+ value
+ }
+ .bits(),
+ "{:?}.remove({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::remove(&mut value, *input);
+ value
+ }
+ .bits(),
+ "Flags::remove({:?}, {:?})",
+ value,
+ input
+ );
+
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_set(&mut value, *input, false);
+ value
+ }
+ .bits(),
+ "{:?}.set({:?}, false)",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::set(&mut value, *input, false);
+ value
+ }
+ .bits(),
+ "Flags::set({:?}, {:?}, false)",
+ value,
+ input
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/symmetric_difference.rs b/third_party/rust/bitflags/src/tests/symmetric_difference.rs
new file mode 100644
index 0000000000..75e9123ac5
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/symmetric_difference.rs
@@ -0,0 +1,110 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::empty(), 0),
+ (TestFlags::all(), 1 | 1 << 1 | 1 << 2),
+ (TestFlags::from_bits_retain(1 << 3), 1 << 3),
+ ],
+ TestFlags::symmetric_difference,
+ TestFlags::toggle,
+ );
+
+ case(
+ TestFlags::A,
+ &[
+ (TestFlags::empty(), 1),
+ (TestFlags::A, 0),
+ (TestFlags::all(), 1 << 1 | 1 << 2),
+ ],
+ TestFlags::symmetric_difference,
+ TestFlags::toggle,
+ );
+
+ case(
+ TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+ &[
+ (TestFlags::ABC, 1 << 2 | 1 << 3),
+ (TestFlags::from_bits_retain(1 << 3), 1 | 1 << 1),
+ ],
+ TestFlags::symmetric_difference,
+ TestFlags::toggle,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::BitXor<Output = T> + std::ops::BitXorAssign + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent_sym_diff: impl FnMut(T, T) -> T,
+ mut inherent_toggle: impl FnMut(&mut T, T),
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent_sym_diff(value, *input).bits(),
+ "{:?}.symmetric_difference({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::symmetric_difference(value, *input).bits(),
+ "Flags::symmetric_difference({:?}, {:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ (value ^ *input).bits(),
+ "{:?} ^ {:?}",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ value ^= *input;
+ value
+ }
+ .bits(),
+ "{:?} ^= {:?}",
+ value,
+ input,
+ );
+
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ inherent_toggle(&mut value, *input);
+ value
+ }
+ .bits(),
+ "{:?}.toggle({:?})",
+ value,
+ input,
+ );
+
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ Flags::toggle(&mut value, *input);
+ value
+ }
+ .bits(),
+ "{:?}.toggle({:?})",
+ value,
+ input,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/tests/union.rs b/third_party/rust/bitflags/src/tests/union.rs
new file mode 100644
index 0000000000..6190681931
--- /dev/null
+++ b/third_party/rust/bitflags/src/tests/union.rs
@@ -0,0 +1,71 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+ case(
+ TestFlags::empty(),
+ &[
+ (TestFlags::A, 1),
+ (TestFlags::all(), 1 | 1 << 1 | 1 << 2),
+ (TestFlags::empty(), 0),
+ (TestFlags::from_bits_retain(1 << 3), 1 << 3),
+ ],
+ TestFlags::union,
+ );
+
+ case(
+ TestFlags::A | TestFlags::C,
+ &[
+ (TestFlags::A | TestFlags::B, 1 | 1 << 1 | 1 << 2),
+ (TestFlags::A, 1 | 1 << 2),
+ ],
+ TestFlags::union,
+ );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::BitOr<Output = T> + std::ops::BitOrAssign + Copy>(
+ value: T,
+ inputs: &[(T, T::Bits)],
+ mut inherent: impl FnMut(T, T) -> T,
+) where
+ T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+ for (input, expected) in inputs {
+ assert_eq!(
+ *expected,
+ inherent(value, *input).bits(),
+ "{:?}.union({:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ Flags::union(value, *input).bits(),
+ "Flags::union({:?}, {:?})",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ (value | *input).bits(),
+ "{:?} | {:?}",
+ value,
+ input
+ );
+ assert_eq!(
+ *expected,
+ {
+ let mut value = value;
+ value |= *input;
+ value
+ }
+ .bits(),
+ "{:?} |= {:?}",
+ value,
+ input,
+ );
+ }
+}
diff --git a/third_party/rust/bitflags/src/traits.rs b/third_party/rust/bitflags/src/traits.rs
index 28235142de..3905d7d5b0 100644
--- a/third_party/rust/bitflags/src/traits.rs
+++ b/third_party/rust/bitflags/src/traits.rs
@@ -11,6 +11,7 @@ use crate::{
/**
A defined flags value that may be named or unnamed.
*/
+#[derive(Debug)]
pub struct Flag<B> {
name: &'static str,
value: B,