174522d2cSopenharmony_ci// Copyright 2014 The Rust Project Developers. See the COPYRIGHT 274522d2cSopenharmony_ci// file at the top-level directory of this distribution and at 374522d2cSopenharmony_ci// http://rust-lang.org/COPYRIGHT. 474522d2cSopenharmony_ci// 574522d2cSopenharmony_ci// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 674522d2cSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 774522d2cSopenharmony_ci// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 874522d2cSopenharmony_ci// option. This file may not be copied, modified, or distributed 974522d2cSopenharmony_ci// except according to those terms. 1074522d2cSopenharmony_ci 1174522d2cSopenharmony_ci//! A typesafe bitmask flag generator useful for sets of C-style bitmask flags. 1274522d2cSopenharmony_ci//! It can be used for creating typesafe wrappers around C APIs. 1374522d2cSopenharmony_ci//! 1474522d2cSopenharmony_ci//! The `bitflags!` macro generates `struct`s that manage a set of flags. The 1574522d2cSopenharmony_ci//! flags should only be defined for integer types, otherwise unexpected type 1674522d2cSopenharmony_ci//! errors may occur at compile time. 1774522d2cSopenharmony_ci//! 1874522d2cSopenharmony_ci//! # Example 1974522d2cSopenharmony_ci//! 2074522d2cSopenharmony_ci//! ``` 2174522d2cSopenharmony_ci//! use bitflags::bitflags; 2274522d2cSopenharmony_ci//! 2374522d2cSopenharmony_ci//! bitflags! { 2474522d2cSopenharmony_ci//! struct Flags: u32 { 2574522d2cSopenharmony_ci//! const A = 0b00000001; 2674522d2cSopenharmony_ci//! const B = 0b00000010; 2774522d2cSopenharmony_ci//! const C = 0b00000100; 2874522d2cSopenharmony_ci//! const ABC = Self::A.bits | Self::B.bits | Self::C.bits; 2974522d2cSopenharmony_ci//! } 3074522d2cSopenharmony_ci//! } 3174522d2cSopenharmony_ci//! 3274522d2cSopenharmony_ci//! fn main() { 3374522d2cSopenharmony_ci//! let e1 = Flags::A | Flags::C; 3474522d2cSopenharmony_ci//! let e2 = Flags::B | Flags::C; 3574522d2cSopenharmony_ci//! assert_eq!((e1 | e2), Flags::ABC); // union 3674522d2cSopenharmony_ci//! assert_eq!((e1 & e2), Flags::C); // intersection 3774522d2cSopenharmony_ci//! assert_eq!((e1 - e2), Flags::A); // set difference 3874522d2cSopenharmony_ci//! assert_eq!(!e2, Flags::A); // set complement 3974522d2cSopenharmony_ci//! } 4074522d2cSopenharmony_ci//! ``` 4174522d2cSopenharmony_ci//! 4274522d2cSopenharmony_ci//! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code 4374522d2cSopenharmony_ci//! generated by the above `bitflags!` expansion. 4474522d2cSopenharmony_ci//! 4574522d2cSopenharmony_ci//! The generated `struct`s can also be extended with type and trait 4674522d2cSopenharmony_ci//! implementations: 4774522d2cSopenharmony_ci//! 4874522d2cSopenharmony_ci//! ``` 4974522d2cSopenharmony_ci//! use std::fmt; 5074522d2cSopenharmony_ci//! 5174522d2cSopenharmony_ci//! use bitflags::bitflags; 5274522d2cSopenharmony_ci//! 5374522d2cSopenharmony_ci//! bitflags! { 5474522d2cSopenharmony_ci//! struct Flags: u32 { 5574522d2cSopenharmony_ci//! const A = 0b00000001; 5674522d2cSopenharmony_ci//! const B = 0b00000010; 5774522d2cSopenharmony_ci//! } 5874522d2cSopenharmony_ci//! } 5974522d2cSopenharmony_ci//! 6074522d2cSopenharmony_ci//! impl Flags { 6174522d2cSopenharmony_ci//! pub fn clear(&mut self) { 6274522d2cSopenharmony_ci//! self.bits = 0; // The `bits` field can be accessed from within the 6374522d2cSopenharmony_ci//! // same module where the `bitflags!` macro was invoked. 6474522d2cSopenharmony_ci//! } 6574522d2cSopenharmony_ci//! } 6674522d2cSopenharmony_ci//! 6774522d2cSopenharmony_ci//! impl fmt::Display for Flags { 6874522d2cSopenharmony_ci//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 6974522d2cSopenharmony_ci//! write!(f, "hi!") 7074522d2cSopenharmony_ci//! } 7174522d2cSopenharmony_ci//! } 7274522d2cSopenharmony_ci//! 7374522d2cSopenharmony_ci//! fn main() { 7474522d2cSopenharmony_ci//! let mut flags = Flags::A | Flags::B; 7574522d2cSopenharmony_ci//! flags.clear(); 7674522d2cSopenharmony_ci//! assert!(flags.is_empty()); 7774522d2cSopenharmony_ci//! assert_eq!(format!("{}", flags), "hi!"); 7874522d2cSopenharmony_ci//! assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); 7974522d2cSopenharmony_ci//! assert_eq!(format!("{:?}", Flags::B), "B"); 8074522d2cSopenharmony_ci//! } 8174522d2cSopenharmony_ci//! ``` 8274522d2cSopenharmony_ci//! 8374522d2cSopenharmony_ci//! # Visibility 8474522d2cSopenharmony_ci//! 8574522d2cSopenharmony_ci//! The generated structs and their associated flag constants are not exported 8674522d2cSopenharmony_ci//! out of the current module by default. A definition can be exported out of 8774522d2cSopenharmony_ci//! the current module by adding `pub` before `struct`: 8874522d2cSopenharmony_ci//! 8974522d2cSopenharmony_ci//! ``` 9074522d2cSopenharmony_ci//! mod example { 9174522d2cSopenharmony_ci//! use bitflags::bitflags; 9274522d2cSopenharmony_ci//! 9374522d2cSopenharmony_ci//! bitflags! { 9474522d2cSopenharmony_ci//! pub struct Flags1: u32 { 9574522d2cSopenharmony_ci//! const A = 0b00000001; 9674522d2cSopenharmony_ci//! } 9774522d2cSopenharmony_ci//! 9874522d2cSopenharmony_ci//! # pub 9974522d2cSopenharmony_ci//! struct Flags2: u32 { 10074522d2cSopenharmony_ci//! const B = 0b00000010; 10174522d2cSopenharmony_ci//! } 10274522d2cSopenharmony_ci//! } 10374522d2cSopenharmony_ci//! } 10474522d2cSopenharmony_ci//! 10574522d2cSopenharmony_ci//! fn main() { 10674522d2cSopenharmony_ci//! let flag1 = example::Flags1::A; 10774522d2cSopenharmony_ci//! let flag2 = example::Flags2::B; // error: const `B` is private 10874522d2cSopenharmony_ci//! } 10974522d2cSopenharmony_ci//! ``` 11074522d2cSopenharmony_ci//! 11174522d2cSopenharmony_ci//! # Attributes 11274522d2cSopenharmony_ci//! 11374522d2cSopenharmony_ci//! Attributes can be attached to the generated `struct`s by placing them 11474522d2cSopenharmony_ci//! before the `struct` keyword. 11574522d2cSopenharmony_ci//! 11674522d2cSopenharmony_ci//! ## Representations 11774522d2cSopenharmony_ci//! 11874522d2cSopenharmony_ci//! It's valid to add a `#[repr(C)]` or `#[repr(transparent)]` attribute to a type 11974522d2cSopenharmony_ci//! generated by `bitflags!`. In these cases, the type is guaranteed to be a newtype. 12074522d2cSopenharmony_ci//! 12174522d2cSopenharmony_ci//! ``` 12274522d2cSopenharmony_ci//! use bitflags::bitflags; 12374522d2cSopenharmony_ci//! 12474522d2cSopenharmony_ci//! bitflags! { 12574522d2cSopenharmony_ci//! #[repr(transparent)] 12674522d2cSopenharmony_ci//! struct Flags: u32 { 12774522d2cSopenharmony_ci//! const A = 0b00000001; 12874522d2cSopenharmony_ci//! const B = 0b00000010; 12974522d2cSopenharmony_ci//! const C = 0b00000100; 13074522d2cSopenharmony_ci//! } 13174522d2cSopenharmony_ci//! } 13274522d2cSopenharmony_ci//! ``` 13374522d2cSopenharmony_ci//! 13474522d2cSopenharmony_ci//! # Trait implementations 13574522d2cSopenharmony_ci//! 13674522d2cSopenharmony_ci//! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` 13774522d2cSopenharmony_ci//! traits are automatically derived for the `struct`s using the `derive` attribute. 13874522d2cSopenharmony_ci//! Additional traits can be derived by providing an explicit `derive` 13974522d2cSopenharmony_ci//! attribute on `struct`. 14074522d2cSopenharmony_ci//! 14174522d2cSopenharmony_ci//! The `Extend` and `FromIterator` traits are implemented for the `struct`s, 14274522d2cSopenharmony_ci//! too: `Extend` adds the union of the instances of the `struct` iterated over, 14374522d2cSopenharmony_ci//! while `FromIterator` calculates the union. 14474522d2cSopenharmony_ci//! 14574522d2cSopenharmony_ci//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` traits are also 14674522d2cSopenharmony_ci//! implemented by displaying the bits value of the internal struct. 14774522d2cSopenharmony_ci//! 14874522d2cSopenharmony_ci//! ## Operators 14974522d2cSopenharmony_ci//! 15074522d2cSopenharmony_ci//! The following operator traits are implemented for the generated `struct`s: 15174522d2cSopenharmony_ci//! 15274522d2cSopenharmony_ci//! - `BitOr` and `BitOrAssign`: union 15374522d2cSopenharmony_ci//! - `BitAnd` and `BitAndAssign`: intersection 15474522d2cSopenharmony_ci//! - `BitXor` and `BitXorAssign`: toggle 15574522d2cSopenharmony_ci//! - `Sub` and `SubAssign`: set difference 15674522d2cSopenharmony_ci//! - `Not`: set complement 15774522d2cSopenharmony_ci//! 15874522d2cSopenharmony_ci//! # Methods 15974522d2cSopenharmony_ci//! 16074522d2cSopenharmony_ci//! The following methods are defined for the generated `struct`s: 16174522d2cSopenharmony_ci//! 16274522d2cSopenharmony_ci//! - `empty`: an empty set of flags 16374522d2cSopenharmony_ci//! - `all`: the set of all defined flags 16474522d2cSopenharmony_ci//! - `bits`: the raw value of the flags currently stored 16574522d2cSopenharmony_ci//! - `from_bits`: convert from underlying bit representation, unless that 16674522d2cSopenharmony_ci//! representation contains bits that do not correspond to a 16774522d2cSopenharmony_ci//! defined flag 16874522d2cSopenharmony_ci//! - `from_bits_truncate`: convert from underlying bit representation, dropping 16974522d2cSopenharmony_ci//! any bits that do not correspond to defined flags 17074522d2cSopenharmony_ci//! - `from_bits_unchecked`: convert from underlying bit representation, keeping 17174522d2cSopenharmony_ci//! all bits (even those not corresponding to defined 17274522d2cSopenharmony_ci//! flags) 17374522d2cSopenharmony_ci//! - `is_empty`: `true` if no flags are currently stored 17474522d2cSopenharmony_ci//! - `is_all`: `true` if currently set flags exactly equal all defined flags 17574522d2cSopenharmony_ci//! - `intersects`: `true` if there are flags common to both `self` and `other` 17674522d2cSopenharmony_ci//! - `contains`: `true` if all of the flags in `other` are contained within `self` 17774522d2cSopenharmony_ci//! - `insert`: inserts the specified flags in-place 17874522d2cSopenharmony_ci//! - `remove`: removes the specified flags in-place 17974522d2cSopenharmony_ci//! - `toggle`: the specified flags will be inserted if not present, and removed 18074522d2cSopenharmony_ci//! if they are. 18174522d2cSopenharmony_ci//! - `set`: inserts or removes the specified flags depending on the passed value 18274522d2cSopenharmony_ci//! - `intersection`: returns a new set of flags, containing only the flags present 18374522d2cSopenharmony_ci//! in both `self` and `other` (the argument to the function). 18474522d2cSopenharmony_ci//! - `union`: returns a new set of flags, containing any flags present in 18574522d2cSopenharmony_ci//! either `self` or `other` (the argument to the function). 18674522d2cSopenharmony_ci//! - `difference`: returns a new set of flags, containing all flags present in 18774522d2cSopenharmony_ci//! `self` without any of the flags present in `other` (the 18874522d2cSopenharmony_ci//! argument to the function). 18974522d2cSopenharmony_ci//! - `symmetric_difference`: returns a new set of flags, containing all flags 19074522d2cSopenharmony_ci//! present in either `self` or `other` (the argument 19174522d2cSopenharmony_ci//! to the function), but not both. 19274522d2cSopenharmony_ci//! - `complement`: returns a new set of flags, containing all flags which are 19374522d2cSopenharmony_ci//! not set in `self`, but which are allowed for this type. 19474522d2cSopenharmony_ci//! 19574522d2cSopenharmony_ci//! ## Default 19674522d2cSopenharmony_ci//! 19774522d2cSopenharmony_ci//! The `Default` trait is not automatically implemented for the generated structs. 19874522d2cSopenharmony_ci//! 19974522d2cSopenharmony_ci//! If your default value is equal to `0` (which is the same value as calling `empty()` 20074522d2cSopenharmony_ci//! on the generated struct), you can simply derive `Default`: 20174522d2cSopenharmony_ci//! 20274522d2cSopenharmony_ci//! ``` 20374522d2cSopenharmony_ci//! use bitflags::bitflags; 20474522d2cSopenharmony_ci//! 20574522d2cSopenharmony_ci//! bitflags! { 20674522d2cSopenharmony_ci//! // Results in default value with bits: 0 20774522d2cSopenharmony_ci//! #[derive(Default)] 20874522d2cSopenharmony_ci//! struct Flags: u32 { 20974522d2cSopenharmony_ci//! const A = 0b00000001; 21074522d2cSopenharmony_ci//! const B = 0b00000010; 21174522d2cSopenharmony_ci//! const C = 0b00000100; 21274522d2cSopenharmony_ci//! } 21374522d2cSopenharmony_ci//! } 21474522d2cSopenharmony_ci//! 21574522d2cSopenharmony_ci//! fn main() { 21674522d2cSopenharmony_ci//! let derived_default: Flags = Default::default(); 21774522d2cSopenharmony_ci//! assert_eq!(derived_default.bits(), 0); 21874522d2cSopenharmony_ci//! } 21974522d2cSopenharmony_ci//! ``` 22074522d2cSopenharmony_ci//! 22174522d2cSopenharmony_ci//! If your default value is not equal to `0` you need to implement `Default` yourself: 22274522d2cSopenharmony_ci//! 22374522d2cSopenharmony_ci//! ``` 22474522d2cSopenharmony_ci//! use bitflags::bitflags; 22574522d2cSopenharmony_ci//! 22674522d2cSopenharmony_ci//! bitflags! { 22774522d2cSopenharmony_ci//! struct Flags: u32 { 22874522d2cSopenharmony_ci//! const A = 0b00000001; 22974522d2cSopenharmony_ci//! const B = 0b00000010; 23074522d2cSopenharmony_ci//! const C = 0b00000100; 23174522d2cSopenharmony_ci//! } 23274522d2cSopenharmony_ci//! } 23374522d2cSopenharmony_ci//! 23474522d2cSopenharmony_ci//! // explicit `Default` implementation 23574522d2cSopenharmony_ci//! impl Default for Flags { 23674522d2cSopenharmony_ci//! fn default() -> Flags { 23774522d2cSopenharmony_ci//! Flags::A | Flags::C 23874522d2cSopenharmony_ci//! } 23974522d2cSopenharmony_ci//! } 24074522d2cSopenharmony_ci//! 24174522d2cSopenharmony_ci//! fn main() { 24274522d2cSopenharmony_ci//! let implemented_default: Flags = Default::default(); 24374522d2cSopenharmony_ci//! assert_eq!(implemented_default, (Flags::A | Flags::C)); 24474522d2cSopenharmony_ci//! } 24574522d2cSopenharmony_ci//! ``` 24674522d2cSopenharmony_ci//! 24774522d2cSopenharmony_ci//! # Zero Flags 24874522d2cSopenharmony_ci//! 24974522d2cSopenharmony_ci//! Flags with a value equal to zero will have some strange behavior that one should be aware of. 25074522d2cSopenharmony_ci//! 25174522d2cSopenharmony_ci//! ``` 25274522d2cSopenharmony_ci//! use bitflags::bitflags; 25374522d2cSopenharmony_ci//! 25474522d2cSopenharmony_ci//! bitflags! { 25574522d2cSopenharmony_ci//! struct Flags: u32 { 25674522d2cSopenharmony_ci//! const NONE = 0b00000000; 25774522d2cSopenharmony_ci//! const SOME = 0b00000001; 25874522d2cSopenharmony_ci//! } 25974522d2cSopenharmony_ci//! } 26074522d2cSopenharmony_ci//! 26174522d2cSopenharmony_ci//! fn main() { 26274522d2cSopenharmony_ci//! let empty = Flags::empty(); 26374522d2cSopenharmony_ci//! let none = Flags::NONE; 26474522d2cSopenharmony_ci//! let some = Flags::SOME; 26574522d2cSopenharmony_ci//! 26674522d2cSopenharmony_ci//! // Zero flags are treated as always present 26774522d2cSopenharmony_ci//! assert!(empty.contains(Flags::NONE)); 26874522d2cSopenharmony_ci//! assert!(none.contains(Flags::NONE)); 26974522d2cSopenharmony_ci//! assert!(some.contains(Flags::NONE)); 27074522d2cSopenharmony_ci//! 27174522d2cSopenharmony_ci//! // Zero flags will be ignored when testing for emptiness 27274522d2cSopenharmony_ci//! assert!(none.is_empty()); 27374522d2cSopenharmony_ci//! } 27474522d2cSopenharmony_ci//! ``` 27574522d2cSopenharmony_ci//! 27674522d2cSopenharmony_ci//! Users should generally avoid defining a flag with a value of zero. 27774522d2cSopenharmony_ci 27874522d2cSopenharmony_ci#![cfg_attr(not(test), no_std)] 27974522d2cSopenharmony_ci#![doc(html_root_url = "https://docs.rs/bitflags/1.3.2")] 28074522d2cSopenharmony_ci 28174522d2cSopenharmony_ci#[doc(hidden)] 28274522d2cSopenharmony_cipub extern crate core as _core; 28374522d2cSopenharmony_ci 28474522d2cSopenharmony_ci/// The macro used to generate the flag structures. 28574522d2cSopenharmony_ci/// 28674522d2cSopenharmony_ci/// See the [crate level docs](../bitflags/index.html) for complete documentation. 28774522d2cSopenharmony_ci/// 28874522d2cSopenharmony_ci/// # Example 28974522d2cSopenharmony_ci/// 29074522d2cSopenharmony_ci/// ``` 29174522d2cSopenharmony_ci/// use bitflags::bitflags; 29274522d2cSopenharmony_ci/// 29374522d2cSopenharmony_ci/// bitflags! { 29474522d2cSopenharmony_ci/// struct Flags: u32 { 29574522d2cSopenharmony_ci/// const A = 0b00000001; 29674522d2cSopenharmony_ci/// const B = 0b00000010; 29774522d2cSopenharmony_ci/// const C = 0b00000100; 29874522d2cSopenharmony_ci/// const ABC = Self::A.bits | Self::B.bits | Self::C.bits; 29974522d2cSopenharmony_ci/// } 30074522d2cSopenharmony_ci/// } 30174522d2cSopenharmony_ci/// 30274522d2cSopenharmony_ci/// fn main() { 30374522d2cSopenharmony_ci/// let e1 = Flags::A | Flags::C; 30474522d2cSopenharmony_ci/// let e2 = Flags::B | Flags::C; 30574522d2cSopenharmony_ci/// assert_eq!((e1 | e2), Flags::ABC); // union 30674522d2cSopenharmony_ci/// assert_eq!((e1 & e2), Flags::C); // intersection 30774522d2cSopenharmony_ci/// assert_eq!((e1 - e2), Flags::A); // set difference 30874522d2cSopenharmony_ci/// assert_eq!(!e2, Flags::A); // set complement 30974522d2cSopenharmony_ci/// } 31074522d2cSopenharmony_ci/// ``` 31174522d2cSopenharmony_ci/// 31274522d2cSopenharmony_ci/// The generated `struct`s can also be extended with type and trait 31374522d2cSopenharmony_ci/// implementations: 31474522d2cSopenharmony_ci/// 31574522d2cSopenharmony_ci/// ``` 31674522d2cSopenharmony_ci/// use std::fmt; 31774522d2cSopenharmony_ci/// 31874522d2cSopenharmony_ci/// use bitflags::bitflags; 31974522d2cSopenharmony_ci/// 32074522d2cSopenharmony_ci/// bitflags! { 32174522d2cSopenharmony_ci/// struct Flags: u32 { 32274522d2cSopenharmony_ci/// const A = 0b00000001; 32374522d2cSopenharmony_ci/// const B = 0b00000010; 32474522d2cSopenharmony_ci/// } 32574522d2cSopenharmony_ci/// } 32674522d2cSopenharmony_ci/// 32774522d2cSopenharmony_ci/// impl Flags { 32874522d2cSopenharmony_ci/// pub fn clear(&mut self) { 32974522d2cSopenharmony_ci/// self.bits = 0; // The `bits` field can be accessed from within the 33074522d2cSopenharmony_ci/// // same module where the `bitflags!` macro was invoked. 33174522d2cSopenharmony_ci/// } 33274522d2cSopenharmony_ci/// } 33374522d2cSopenharmony_ci/// 33474522d2cSopenharmony_ci/// impl fmt::Display for Flags { 33574522d2cSopenharmony_ci/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 33674522d2cSopenharmony_ci/// write!(f, "hi!") 33774522d2cSopenharmony_ci/// } 33874522d2cSopenharmony_ci/// } 33974522d2cSopenharmony_ci/// 34074522d2cSopenharmony_ci/// fn main() { 34174522d2cSopenharmony_ci/// let mut flags = Flags::A | Flags::B; 34274522d2cSopenharmony_ci/// flags.clear(); 34374522d2cSopenharmony_ci/// assert!(flags.is_empty()); 34474522d2cSopenharmony_ci/// assert_eq!(format!("{}", flags), "hi!"); 34574522d2cSopenharmony_ci/// assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); 34674522d2cSopenharmony_ci/// assert_eq!(format!("{:?}", Flags::B), "B"); 34774522d2cSopenharmony_ci/// } 34874522d2cSopenharmony_ci/// ``` 34974522d2cSopenharmony_ci#[macro_export(local_inner_macros)] 35074522d2cSopenharmony_cimacro_rules! bitflags { 35174522d2cSopenharmony_ci ( 35274522d2cSopenharmony_ci $(#[$outer:meta])* 35374522d2cSopenharmony_ci $vis:vis struct $BitFlags:ident: $T:ty { 35474522d2cSopenharmony_ci $( 35574522d2cSopenharmony_ci $(#[$inner:ident $($args:tt)*])* 35674522d2cSopenharmony_ci const $Flag:ident = $value:expr; 35774522d2cSopenharmony_ci )* 35874522d2cSopenharmony_ci } 35974522d2cSopenharmony_ci 36074522d2cSopenharmony_ci $($t:tt)* 36174522d2cSopenharmony_ci ) => { 36274522d2cSopenharmony_ci $(#[$outer])* 36374522d2cSopenharmony_ci #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] 36474522d2cSopenharmony_ci $vis struct $BitFlags { 36574522d2cSopenharmony_ci bits: $T, 36674522d2cSopenharmony_ci } 36774522d2cSopenharmony_ci 36874522d2cSopenharmony_ci __impl_bitflags! { 36974522d2cSopenharmony_ci $BitFlags: $T { 37074522d2cSopenharmony_ci $( 37174522d2cSopenharmony_ci $(#[$inner $($args)*])* 37274522d2cSopenharmony_ci $Flag = $value; 37374522d2cSopenharmony_ci )* 37474522d2cSopenharmony_ci } 37574522d2cSopenharmony_ci } 37674522d2cSopenharmony_ci 37774522d2cSopenharmony_ci bitflags! { 37874522d2cSopenharmony_ci $($t)* 37974522d2cSopenharmony_ci } 38074522d2cSopenharmony_ci }; 38174522d2cSopenharmony_ci () => {}; 38274522d2cSopenharmony_ci} 38374522d2cSopenharmony_ci 38474522d2cSopenharmony_ci// A helper macro to implement the `all` function. 38574522d2cSopenharmony_ci#[macro_export(local_inner_macros)] 38674522d2cSopenharmony_ci#[doc(hidden)] 38774522d2cSopenharmony_cimacro_rules! __impl_all_bitflags { 38874522d2cSopenharmony_ci ( 38974522d2cSopenharmony_ci $BitFlags:ident: $T:ty { 39074522d2cSopenharmony_ci $( 39174522d2cSopenharmony_ci $(#[$attr:ident $($args:tt)*])* 39274522d2cSopenharmony_ci $Flag:ident = $value:expr; 39374522d2cSopenharmony_ci )+ 39474522d2cSopenharmony_ci } 39574522d2cSopenharmony_ci ) => { 39674522d2cSopenharmony_ci // See `Debug::fmt` for why this approach is taken. 39774522d2cSopenharmony_ci #[allow(non_snake_case)] 39874522d2cSopenharmony_ci trait __BitFlags { 39974522d2cSopenharmony_ci $( 40074522d2cSopenharmony_ci const $Flag: $T = 0; 40174522d2cSopenharmony_ci )+ 40274522d2cSopenharmony_ci } 40374522d2cSopenharmony_ci #[allow(non_snake_case)] 40474522d2cSopenharmony_ci impl __BitFlags for $BitFlags { 40574522d2cSopenharmony_ci $( 40674522d2cSopenharmony_ci __impl_bitflags! { 40774522d2cSopenharmony_ci #[allow(deprecated)] 40874522d2cSopenharmony_ci $(? #[$attr $($args)*])* 40974522d2cSopenharmony_ci const $Flag: $T = Self::$Flag.bits; 41074522d2cSopenharmony_ci } 41174522d2cSopenharmony_ci )+ 41274522d2cSopenharmony_ci } 41374522d2cSopenharmony_ci Self { bits: $(<Self as __BitFlags>::$Flag)|+ } 41474522d2cSopenharmony_ci }; 41574522d2cSopenharmony_ci ( 41674522d2cSopenharmony_ci $BitFlags:ident: $T:ty { } 41774522d2cSopenharmony_ci ) => { 41874522d2cSopenharmony_ci Self { bits: 0 } 41974522d2cSopenharmony_ci }; 42074522d2cSopenharmony_ci} 42174522d2cSopenharmony_ci 42274522d2cSopenharmony_ci#[macro_export(local_inner_macros)] 42374522d2cSopenharmony_ci#[doc(hidden)] 42474522d2cSopenharmony_cimacro_rules! __impl_bitflags { 42574522d2cSopenharmony_ci ( 42674522d2cSopenharmony_ci $BitFlags:ident: $T:ty { 42774522d2cSopenharmony_ci $( 42874522d2cSopenharmony_ci $(#[$attr:ident $($args:tt)*])* 42974522d2cSopenharmony_ci $Flag:ident = $value:expr; 43074522d2cSopenharmony_ci )* 43174522d2cSopenharmony_ci } 43274522d2cSopenharmony_ci ) => { 43374522d2cSopenharmony_ci impl $crate::_core::fmt::Debug for $BitFlags { 43474522d2cSopenharmony_ci fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { 43574522d2cSopenharmony_ci // This convoluted approach is to handle #[cfg]-based flag 43674522d2cSopenharmony_ci // omission correctly. For example it needs to support: 43774522d2cSopenharmony_ci // 43874522d2cSopenharmony_ci // #[cfg(unix)] const A: Flag = /* ... */; 43974522d2cSopenharmony_ci // #[cfg(windows)] const B: Flag = /* ... */; 44074522d2cSopenharmony_ci 44174522d2cSopenharmony_ci // Unconditionally define a check for every flag, even disabled 44274522d2cSopenharmony_ci // ones. 44374522d2cSopenharmony_ci #[allow(non_snake_case)] 44474522d2cSopenharmony_ci trait __BitFlags { 44574522d2cSopenharmony_ci $( 44674522d2cSopenharmony_ci #[inline] 44774522d2cSopenharmony_ci fn $Flag(&self) -> bool { false } 44874522d2cSopenharmony_ci )* 44974522d2cSopenharmony_ci } 45074522d2cSopenharmony_ci 45174522d2cSopenharmony_ci // Conditionally override the check for just those flags that 45274522d2cSopenharmony_ci // are not #[cfg]ed away. 45374522d2cSopenharmony_ci #[allow(non_snake_case)] 45474522d2cSopenharmony_ci impl __BitFlags for $BitFlags { 45574522d2cSopenharmony_ci $( 45674522d2cSopenharmony_ci __impl_bitflags! { 45774522d2cSopenharmony_ci #[allow(deprecated)] 45874522d2cSopenharmony_ci #[inline] 45974522d2cSopenharmony_ci $(? #[$attr $($args)*])* 46074522d2cSopenharmony_ci fn $Flag(&self) -> bool { 46174522d2cSopenharmony_ci if Self::$Flag.bits == 0 && self.bits != 0 { 46274522d2cSopenharmony_ci false 46374522d2cSopenharmony_ci } else { 46474522d2cSopenharmony_ci self.bits & Self::$Flag.bits == Self::$Flag.bits 46574522d2cSopenharmony_ci } 46674522d2cSopenharmony_ci } 46774522d2cSopenharmony_ci } 46874522d2cSopenharmony_ci )* 46974522d2cSopenharmony_ci } 47074522d2cSopenharmony_ci 47174522d2cSopenharmony_ci let mut first = true; 47274522d2cSopenharmony_ci $( 47374522d2cSopenharmony_ci if <Self as __BitFlags>::$Flag(self) { 47474522d2cSopenharmony_ci if !first { 47574522d2cSopenharmony_ci f.write_str(" | ")?; 47674522d2cSopenharmony_ci } 47774522d2cSopenharmony_ci first = false; 47874522d2cSopenharmony_ci f.write_str($crate::_core::stringify!($Flag))?; 47974522d2cSopenharmony_ci } 48074522d2cSopenharmony_ci )* 48174522d2cSopenharmony_ci let extra_bits = self.bits & !Self::all().bits(); 48274522d2cSopenharmony_ci if extra_bits != 0 { 48374522d2cSopenharmony_ci if !first { 48474522d2cSopenharmony_ci f.write_str(" | ")?; 48574522d2cSopenharmony_ci } 48674522d2cSopenharmony_ci first = false; 48774522d2cSopenharmony_ci f.write_str("0x")?; 48874522d2cSopenharmony_ci $crate::_core::fmt::LowerHex::fmt(&extra_bits, f)?; 48974522d2cSopenharmony_ci } 49074522d2cSopenharmony_ci if first { 49174522d2cSopenharmony_ci f.write_str("(empty)")?; 49274522d2cSopenharmony_ci } 49374522d2cSopenharmony_ci Ok(()) 49474522d2cSopenharmony_ci } 49574522d2cSopenharmony_ci } 49674522d2cSopenharmony_ci impl $crate::_core::fmt::Binary for $BitFlags { 49774522d2cSopenharmony_ci fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { 49874522d2cSopenharmony_ci $crate::_core::fmt::Binary::fmt(&self.bits, f) 49974522d2cSopenharmony_ci } 50074522d2cSopenharmony_ci } 50174522d2cSopenharmony_ci impl $crate::_core::fmt::Octal for $BitFlags { 50274522d2cSopenharmony_ci fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { 50374522d2cSopenharmony_ci $crate::_core::fmt::Octal::fmt(&self.bits, f) 50474522d2cSopenharmony_ci } 50574522d2cSopenharmony_ci } 50674522d2cSopenharmony_ci impl $crate::_core::fmt::LowerHex for $BitFlags { 50774522d2cSopenharmony_ci fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { 50874522d2cSopenharmony_ci $crate::_core::fmt::LowerHex::fmt(&self.bits, f) 50974522d2cSopenharmony_ci } 51074522d2cSopenharmony_ci } 51174522d2cSopenharmony_ci impl $crate::_core::fmt::UpperHex for $BitFlags { 51274522d2cSopenharmony_ci fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { 51374522d2cSopenharmony_ci $crate::_core::fmt::UpperHex::fmt(&self.bits, f) 51474522d2cSopenharmony_ci } 51574522d2cSopenharmony_ci } 51674522d2cSopenharmony_ci 51774522d2cSopenharmony_ci #[allow(dead_code)] 51874522d2cSopenharmony_ci impl $BitFlags { 51974522d2cSopenharmony_ci $( 52074522d2cSopenharmony_ci $(#[$attr $($args)*])* 52174522d2cSopenharmony_ci pub const $Flag: Self = Self { bits: $value }; 52274522d2cSopenharmony_ci )* 52374522d2cSopenharmony_ci 52474522d2cSopenharmony_ci /// Returns an empty set of flags. 52574522d2cSopenharmony_ci #[inline] 52674522d2cSopenharmony_ci pub const fn empty() -> Self { 52774522d2cSopenharmony_ci Self { bits: 0 } 52874522d2cSopenharmony_ci } 52974522d2cSopenharmony_ci 53074522d2cSopenharmony_ci /// Returns the set containing all flags. 53174522d2cSopenharmony_ci #[inline] 53274522d2cSopenharmony_ci pub const fn all() -> Self { 53374522d2cSopenharmony_ci __impl_all_bitflags! { 53474522d2cSopenharmony_ci $BitFlags: $T { 53574522d2cSopenharmony_ci $( 53674522d2cSopenharmony_ci $(#[$attr $($args)*])* 53774522d2cSopenharmony_ci $Flag = $value; 53874522d2cSopenharmony_ci )* 53974522d2cSopenharmony_ci } 54074522d2cSopenharmony_ci } 54174522d2cSopenharmony_ci } 54274522d2cSopenharmony_ci 54374522d2cSopenharmony_ci /// Returns the raw value of the flags currently stored. 54474522d2cSopenharmony_ci #[inline] 54574522d2cSopenharmony_ci pub const fn bits(&self) -> $T { 54674522d2cSopenharmony_ci self.bits 54774522d2cSopenharmony_ci } 54874522d2cSopenharmony_ci 54974522d2cSopenharmony_ci /// Convert from underlying bit representation, unless that 55074522d2cSopenharmony_ci /// representation contains bits that do not correspond to a flag. 55174522d2cSopenharmony_ci #[inline] 55274522d2cSopenharmony_ci pub const fn from_bits(bits: $T) -> $crate::_core::option::Option<Self> { 55374522d2cSopenharmony_ci if (bits & !Self::all().bits()) == 0 { 55474522d2cSopenharmony_ci $crate::_core::option::Option::Some(Self { bits }) 55574522d2cSopenharmony_ci } else { 55674522d2cSopenharmony_ci $crate::_core::option::Option::None 55774522d2cSopenharmony_ci } 55874522d2cSopenharmony_ci } 55974522d2cSopenharmony_ci 56074522d2cSopenharmony_ci /// Convert from underlying bit representation, dropping any bits 56174522d2cSopenharmony_ci /// that do not correspond to flags. 56274522d2cSopenharmony_ci #[inline] 56374522d2cSopenharmony_ci pub const fn from_bits_truncate(bits: $T) -> Self { 56474522d2cSopenharmony_ci Self { bits: bits & Self::all().bits } 56574522d2cSopenharmony_ci } 56674522d2cSopenharmony_ci 56774522d2cSopenharmony_ci /// Convert from underlying bit representation, preserving all 56874522d2cSopenharmony_ci /// bits (even those not corresponding to a defined flag). 56974522d2cSopenharmony_ci /// 57074522d2cSopenharmony_ci /// # Safety 57174522d2cSopenharmony_ci /// 57274522d2cSopenharmony_ci /// The caller of the `bitflags!` macro can chose to allow or 57374522d2cSopenharmony_ci /// disallow extra bits for their bitflags type. 57474522d2cSopenharmony_ci /// 57574522d2cSopenharmony_ci /// The caller of `from_bits_unchecked()` has to ensure that 57674522d2cSopenharmony_ci /// all bits correspond to a defined flag or that extra bits 57774522d2cSopenharmony_ci /// are valid for this bitflags type. 57874522d2cSopenharmony_ci #[inline] 57974522d2cSopenharmony_ci pub const unsafe fn from_bits_unchecked(bits: $T) -> Self { 58074522d2cSopenharmony_ci Self { bits } 58174522d2cSopenharmony_ci } 58274522d2cSopenharmony_ci 58374522d2cSopenharmony_ci /// Returns `true` if no flags are currently stored. 58474522d2cSopenharmony_ci #[inline] 58574522d2cSopenharmony_ci pub const fn is_empty(&self) -> bool { 58674522d2cSopenharmony_ci self.bits() == Self::empty().bits() 58774522d2cSopenharmony_ci } 58874522d2cSopenharmony_ci 58974522d2cSopenharmony_ci /// Returns `true` if all flags are currently set. 59074522d2cSopenharmony_ci #[inline] 59174522d2cSopenharmony_ci pub const fn is_all(&self) -> bool { 59274522d2cSopenharmony_ci Self::all().bits | self.bits == self.bits 59374522d2cSopenharmony_ci } 59474522d2cSopenharmony_ci 59574522d2cSopenharmony_ci /// Returns `true` if there are flags common to both `self` and `other`. 59674522d2cSopenharmony_ci #[inline] 59774522d2cSopenharmony_ci pub const fn intersects(&self, other: Self) -> bool { 59874522d2cSopenharmony_ci !(Self { bits: self.bits & other.bits}).is_empty() 59974522d2cSopenharmony_ci } 60074522d2cSopenharmony_ci 60174522d2cSopenharmony_ci /// Returns `true` if all of the flags in `other` are contained within `self`. 60274522d2cSopenharmony_ci #[inline] 60374522d2cSopenharmony_ci pub const fn contains(&self, other: Self) -> bool { 60474522d2cSopenharmony_ci (self.bits & other.bits) == other.bits 60574522d2cSopenharmony_ci } 60674522d2cSopenharmony_ci 60774522d2cSopenharmony_ci /// Inserts the specified flags in-place. 60874522d2cSopenharmony_ci #[inline] 60974522d2cSopenharmony_ci pub fn insert(&mut self, other: Self) { 61074522d2cSopenharmony_ci self.bits |= other.bits; 61174522d2cSopenharmony_ci } 61274522d2cSopenharmony_ci 61374522d2cSopenharmony_ci /// Removes the specified flags in-place. 61474522d2cSopenharmony_ci #[inline] 61574522d2cSopenharmony_ci pub fn remove(&mut self, other: Self) { 61674522d2cSopenharmony_ci self.bits &= !other.bits; 61774522d2cSopenharmony_ci } 61874522d2cSopenharmony_ci 61974522d2cSopenharmony_ci /// Toggles the specified flags in-place. 62074522d2cSopenharmony_ci #[inline] 62174522d2cSopenharmony_ci pub fn toggle(&mut self, other: Self) { 62274522d2cSopenharmony_ci self.bits ^= other.bits; 62374522d2cSopenharmony_ci } 62474522d2cSopenharmony_ci 62574522d2cSopenharmony_ci /// Inserts or removes the specified flags depending on the passed value. 62674522d2cSopenharmony_ci #[inline] 62774522d2cSopenharmony_ci pub fn set(&mut self, other: Self, value: bool) { 62874522d2cSopenharmony_ci if value { 62974522d2cSopenharmony_ci self.insert(other); 63074522d2cSopenharmony_ci } else { 63174522d2cSopenharmony_ci self.remove(other); 63274522d2cSopenharmony_ci } 63374522d2cSopenharmony_ci } 63474522d2cSopenharmony_ci 63574522d2cSopenharmony_ci /// Returns the intersection between the flags in `self` and 63674522d2cSopenharmony_ci /// `other`. 63774522d2cSopenharmony_ci /// 63874522d2cSopenharmony_ci /// Specifically, the returned set contains only the flags which are 63974522d2cSopenharmony_ci /// present in *both* `self` *and* `other`. 64074522d2cSopenharmony_ci /// 64174522d2cSopenharmony_ci /// This is equivalent to using the `&` operator (e.g. 64274522d2cSopenharmony_ci /// [`ops::BitAnd`]), as in `flags & other`. 64374522d2cSopenharmony_ci /// 64474522d2cSopenharmony_ci /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html 64574522d2cSopenharmony_ci #[inline] 64674522d2cSopenharmony_ci #[must_use] 64774522d2cSopenharmony_ci pub const fn intersection(self, other: Self) -> Self { 64874522d2cSopenharmony_ci Self { bits: self.bits & other.bits } 64974522d2cSopenharmony_ci } 65074522d2cSopenharmony_ci 65174522d2cSopenharmony_ci /// Returns the union of between the flags in `self` and `other`. 65274522d2cSopenharmony_ci /// 65374522d2cSopenharmony_ci /// Specifically, the returned set contains all flags which are 65474522d2cSopenharmony_ci /// present in *either* `self` *or* `other`, including any which are 65574522d2cSopenharmony_ci /// present in both (see [`Self::symmetric_difference`] if that 65674522d2cSopenharmony_ci /// is undesirable). 65774522d2cSopenharmony_ci /// 65874522d2cSopenharmony_ci /// This is equivalent to using the `|` operator (e.g. 65974522d2cSopenharmony_ci /// [`ops::BitOr`]), as in `flags | other`. 66074522d2cSopenharmony_ci /// 66174522d2cSopenharmony_ci /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html 66274522d2cSopenharmony_ci #[inline] 66374522d2cSopenharmony_ci #[must_use] 66474522d2cSopenharmony_ci pub const fn union(self, other: Self) -> Self { 66574522d2cSopenharmony_ci Self { bits: self.bits | other.bits } 66674522d2cSopenharmony_ci } 66774522d2cSopenharmony_ci 66874522d2cSopenharmony_ci /// Returns the difference between the flags in `self` and `other`. 66974522d2cSopenharmony_ci /// 67074522d2cSopenharmony_ci /// Specifically, the returned set contains all flags present in 67174522d2cSopenharmony_ci /// `self`, except for the ones present in `other`. 67274522d2cSopenharmony_ci /// 67374522d2cSopenharmony_ci /// It is also conceptually equivalent to the "bit-clear" operation: 67474522d2cSopenharmony_ci /// `flags & !other` (and this syntax is also supported). 67574522d2cSopenharmony_ci /// 67674522d2cSopenharmony_ci /// This is equivalent to using the `-` operator (e.g. 67774522d2cSopenharmony_ci /// [`ops::Sub`]), as in `flags - other`. 67874522d2cSopenharmony_ci /// 67974522d2cSopenharmony_ci /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html 68074522d2cSopenharmony_ci #[inline] 68174522d2cSopenharmony_ci #[must_use] 68274522d2cSopenharmony_ci pub const fn difference(self, other: Self) -> Self { 68374522d2cSopenharmony_ci Self { bits: self.bits & !other.bits } 68474522d2cSopenharmony_ci } 68574522d2cSopenharmony_ci 68674522d2cSopenharmony_ci /// Returns the [symmetric difference][sym-diff] between the flags 68774522d2cSopenharmony_ci /// in `self` and `other`. 68874522d2cSopenharmony_ci /// 68974522d2cSopenharmony_ci /// Specifically, the returned set contains the flags present which 69074522d2cSopenharmony_ci /// are present in `self` or `other`, but that are not present in 69174522d2cSopenharmony_ci /// both. Equivalently, it contains the flags present in *exactly 69274522d2cSopenharmony_ci /// one* of the sets `self` and `other`. 69374522d2cSopenharmony_ci /// 69474522d2cSopenharmony_ci /// This is equivalent to using the `^` operator (e.g. 69574522d2cSopenharmony_ci /// [`ops::BitXor`]), as in `flags ^ other`. 69674522d2cSopenharmony_ci /// 69774522d2cSopenharmony_ci /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference 69874522d2cSopenharmony_ci /// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html 69974522d2cSopenharmony_ci #[inline] 70074522d2cSopenharmony_ci #[must_use] 70174522d2cSopenharmony_ci pub const fn symmetric_difference(self, other: Self) -> Self { 70274522d2cSopenharmony_ci Self { bits: self.bits ^ other.bits } 70374522d2cSopenharmony_ci } 70474522d2cSopenharmony_ci 70574522d2cSopenharmony_ci /// Returns the complement of this set of flags. 70674522d2cSopenharmony_ci /// 70774522d2cSopenharmony_ci /// Specifically, the returned set contains all the flags which are 70874522d2cSopenharmony_ci /// not set in `self`, but which are allowed for this type. 70974522d2cSopenharmony_ci /// 71074522d2cSopenharmony_ci /// Alternatively, it can be thought of as the set difference 71174522d2cSopenharmony_ci /// between [`Self::all()`] and `self` (e.g. `Self::all() - self`) 71274522d2cSopenharmony_ci /// 71374522d2cSopenharmony_ci /// This is equivalent to using the `!` operator (e.g. 71474522d2cSopenharmony_ci /// [`ops::Not`]), as in `!flags`. 71574522d2cSopenharmony_ci /// 71674522d2cSopenharmony_ci /// [`Self::all()`]: Self::all 71774522d2cSopenharmony_ci /// [`ops::Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html 71874522d2cSopenharmony_ci #[inline] 71974522d2cSopenharmony_ci #[must_use] 72074522d2cSopenharmony_ci pub const fn complement(self) -> Self { 72174522d2cSopenharmony_ci Self::from_bits_truncate(!self.bits) 72274522d2cSopenharmony_ci } 72374522d2cSopenharmony_ci 72474522d2cSopenharmony_ci } 72574522d2cSopenharmony_ci 72674522d2cSopenharmony_ci impl $crate::_core::ops::BitOr for $BitFlags { 72774522d2cSopenharmony_ci type Output = Self; 72874522d2cSopenharmony_ci 72974522d2cSopenharmony_ci /// Returns the union of the two sets of flags. 73074522d2cSopenharmony_ci #[inline] 73174522d2cSopenharmony_ci fn bitor(self, other: $BitFlags) -> Self { 73274522d2cSopenharmony_ci Self { bits: self.bits | other.bits } 73374522d2cSopenharmony_ci } 73474522d2cSopenharmony_ci } 73574522d2cSopenharmony_ci 73674522d2cSopenharmony_ci impl $crate::_core::ops::BitOrAssign for $BitFlags { 73774522d2cSopenharmony_ci /// Adds the set of flags. 73874522d2cSopenharmony_ci #[inline] 73974522d2cSopenharmony_ci fn bitor_assign(&mut self, other: Self) { 74074522d2cSopenharmony_ci self.bits |= other.bits; 74174522d2cSopenharmony_ci } 74274522d2cSopenharmony_ci } 74374522d2cSopenharmony_ci 74474522d2cSopenharmony_ci impl $crate::_core::ops::BitXor for $BitFlags { 74574522d2cSopenharmony_ci type Output = Self; 74674522d2cSopenharmony_ci 74774522d2cSopenharmony_ci /// Returns the left flags, but with all the right flags toggled. 74874522d2cSopenharmony_ci #[inline] 74974522d2cSopenharmony_ci fn bitxor(self, other: Self) -> Self { 75074522d2cSopenharmony_ci Self { bits: self.bits ^ other.bits } 75174522d2cSopenharmony_ci } 75274522d2cSopenharmony_ci } 75374522d2cSopenharmony_ci 75474522d2cSopenharmony_ci impl $crate::_core::ops::BitXorAssign for $BitFlags { 75574522d2cSopenharmony_ci /// Toggles the set of flags. 75674522d2cSopenharmony_ci #[inline] 75774522d2cSopenharmony_ci fn bitxor_assign(&mut self, other: Self) { 75874522d2cSopenharmony_ci self.bits ^= other.bits; 75974522d2cSopenharmony_ci } 76074522d2cSopenharmony_ci } 76174522d2cSopenharmony_ci 76274522d2cSopenharmony_ci impl $crate::_core::ops::BitAnd for $BitFlags { 76374522d2cSopenharmony_ci type Output = Self; 76474522d2cSopenharmony_ci 76574522d2cSopenharmony_ci /// Returns the intersection between the two sets of flags. 76674522d2cSopenharmony_ci #[inline] 76774522d2cSopenharmony_ci fn bitand(self, other: Self) -> Self { 76874522d2cSopenharmony_ci Self { bits: self.bits & other.bits } 76974522d2cSopenharmony_ci } 77074522d2cSopenharmony_ci } 77174522d2cSopenharmony_ci 77274522d2cSopenharmony_ci impl $crate::_core::ops::BitAndAssign for $BitFlags { 77374522d2cSopenharmony_ci /// Disables all flags disabled in the set. 77474522d2cSopenharmony_ci #[inline] 77574522d2cSopenharmony_ci fn bitand_assign(&mut self, other: Self) { 77674522d2cSopenharmony_ci self.bits &= other.bits; 77774522d2cSopenharmony_ci } 77874522d2cSopenharmony_ci } 77974522d2cSopenharmony_ci 78074522d2cSopenharmony_ci impl $crate::_core::ops::Sub for $BitFlags { 78174522d2cSopenharmony_ci type Output = Self; 78274522d2cSopenharmony_ci 78374522d2cSopenharmony_ci /// Returns the set difference of the two sets of flags. 78474522d2cSopenharmony_ci #[inline] 78574522d2cSopenharmony_ci fn sub(self, other: Self) -> Self { 78674522d2cSopenharmony_ci Self { bits: self.bits & !other.bits } 78774522d2cSopenharmony_ci } 78874522d2cSopenharmony_ci } 78974522d2cSopenharmony_ci 79074522d2cSopenharmony_ci impl $crate::_core::ops::SubAssign for $BitFlags { 79174522d2cSopenharmony_ci /// Disables all flags enabled in the set. 79274522d2cSopenharmony_ci #[inline] 79374522d2cSopenharmony_ci fn sub_assign(&mut self, other: Self) { 79474522d2cSopenharmony_ci self.bits &= !other.bits; 79574522d2cSopenharmony_ci } 79674522d2cSopenharmony_ci } 79774522d2cSopenharmony_ci 79874522d2cSopenharmony_ci impl $crate::_core::ops::Not for $BitFlags { 79974522d2cSopenharmony_ci type Output = Self; 80074522d2cSopenharmony_ci 80174522d2cSopenharmony_ci /// Returns the complement of this set of flags. 80274522d2cSopenharmony_ci #[inline] 80374522d2cSopenharmony_ci fn not(self) -> Self { 80474522d2cSopenharmony_ci Self { bits: !self.bits } & Self::all() 80574522d2cSopenharmony_ci } 80674522d2cSopenharmony_ci } 80774522d2cSopenharmony_ci 80874522d2cSopenharmony_ci impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags { 80974522d2cSopenharmony_ci fn extend<T: $crate::_core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) { 81074522d2cSopenharmony_ci for item in iterator { 81174522d2cSopenharmony_ci self.insert(item) 81274522d2cSopenharmony_ci } 81374522d2cSopenharmony_ci } 81474522d2cSopenharmony_ci } 81574522d2cSopenharmony_ci 81674522d2cSopenharmony_ci impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags { 81774522d2cSopenharmony_ci fn from_iter<T: $crate::_core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self { 81874522d2cSopenharmony_ci let mut result = Self::empty(); 81974522d2cSopenharmony_ci result.extend(iterator); 82074522d2cSopenharmony_ci result 82174522d2cSopenharmony_ci } 82274522d2cSopenharmony_ci } 82374522d2cSopenharmony_ci }; 82474522d2cSopenharmony_ci 82574522d2cSopenharmony_ci // Every attribute that the user writes on a const is applied to the 82674522d2cSopenharmony_ci // corresponding const that we generate, but within the implementation of 82774522d2cSopenharmony_ci // Debug and all() we want to ignore everything but #[cfg] attributes. In 82874522d2cSopenharmony_ci // particular, including a #[deprecated] attribute on those items would fail 82974522d2cSopenharmony_ci // to compile. 83074522d2cSopenharmony_ci // https://github.com/bitflags/bitflags/issues/109 83174522d2cSopenharmony_ci // 83274522d2cSopenharmony_ci // Input: 83374522d2cSopenharmony_ci // 83474522d2cSopenharmony_ci // ? #[cfg(feature = "advanced")] 83574522d2cSopenharmony_ci // ? #[deprecated(note = "Use something else.")] 83674522d2cSopenharmony_ci // ? #[doc = r"High quality documentation."] 83774522d2cSopenharmony_ci // fn f() -> i32 { /* ... */ } 83874522d2cSopenharmony_ci // 83974522d2cSopenharmony_ci // Output: 84074522d2cSopenharmony_ci // 84174522d2cSopenharmony_ci // #[cfg(feature = "advanced")] 84274522d2cSopenharmony_ci // fn f() -> i32 { /* ... */ } 84374522d2cSopenharmony_ci ( 84474522d2cSopenharmony_ci $(#[$filtered:meta])* 84574522d2cSopenharmony_ci ? #[cfg $($cfgargs:tt)*] 84674522d2cSopenharmony_ci $(? #[$rest:ident $($restargs:tt)*])* 84774522d2cSopenharmony_ci fn $($item:tt)* 84874522d2cSopenharmony_ci ) => { 84974522d2cSopenharmony_ci __impl_bitflags! { 85074522d2cSopenharmony_ci $(#[$filtered])* 85174522d2cSopenharmony_ci #[cfg $($cfgargs)*] 85274522d2cSopenharmony_ci $(? #[$rest $($restargs)*])* 85374522d2cSopenharmony_ci fn $($item)* 85474522d2cSopenharmony_ci } 85574522d2cSopenharmony_ci }; 85674522d2cSopenharmony_ci ( 85774522d2cSopenharmony_ci $(#[$filtered:meta])* 85874522d2cSopenharmony_ci // $next != `cfg` 85974522d2cSopenharmony_ci ? #[$next:ident $($nextargs:tt)*] 86074522d2cSopenharmony_ci $(? #[$rest:ident $($restargs:tt)*])* 86174522d2cSopenharmony_ci fn $($item:tt)* 86274522d2cSopenharmony_ci ) => { 86374522d2cSopenharmony_ci __impl_bitflags! { 86474522d2cSopenharmony_ci $(#[$filtered])* 86574522d2cSopenharmony_ci // $next filtered out 86674522d2cSopenharmony_ci $(? #[$rest $($restargs)*])* 86774522d2cSopenharmony_ci fn $($item)* 86874522d2cSopenharmony_ci } 86974522d2cSopenharmony_ci }; 87074522d2cSopenharmony_ci ( 87174522d2cSopenharmony_ci $(#[$filtered:meta])* 87274522d2cSopenharmony_ci fn $($item:tt)* 87374522d2cSopenharmony_ci ) => { 87474522d2cSopenharmony_ci $(#[$filtered])* 87574522d2cSopenharmony_ci fn $($item)* 87674522d2cSopenharmony_ci }; 87774522d2cSopenharmony_ci 87874522d2cSopenharmony_ci // Every attribute that the user writes on a const is applied to the 87974522d2cSopenharmony_ci // corresponding const that we generate, but within the implementation of 88074522d2cSopenharmony_ci // Debug and all() we want to ignore everything but #[cfg] attributes. In 88174522d2cSopenharmony_ci // particular, including a #[deprecated] attribute on those items would fail 88274522d2cSopenharmony_ci // to compile. 88374522d2cSopenharmony_ci // https://github.com/bitflags/bitflags/issues/109 88474522d2cSopenharmony_ci // 88574522d2cSopenharmony_ci // const version 88674522d2cSopenharmony_ci // 88774522d2cSopenharmony_ci // Input: 88874522d2cSopenharmony_ci // 88974522d2cSopenharmony_ci // ? #[cfg(feature = "advanced")] 89074522d2cSopenharmony_ci // ? #[deprecated(note = "Use something else.")] 89174522d2cSopenharmony_ci // ? #[doc = r"High quality documentation."] 89274522d2cSopenharmony_ci // const f: i32 { /* ... */ } 89374522d2cSopenharmony_ci // 89474522d2cSopenharmony_ci // Output: 89574522d2cSopenharmony_ci // 89674522d2cSopenharmony_ci // #[cfg(feature = "advanced")] 89774522d2cSopenharmony_ci // const f: i32 { /* ... */ } 89874522d2cSopenharmony_ci ( 89974522d2cSopenharmony_ci $(#[$filtered:meta])* 90074522d2cSopenharmony_ci ? #[cfg $($cfgargs:tt)*] 90174522d2cSopenharmony_ci $(? #[$rest:ident $($restargs:tt)*])* 90274522d2cSopenharmony_ci const $($item:tt)* 90374522d2cSopenharmony_ci ) => { 90474522d2cSopenharmony_ci __impl_bitflags! { 90574522d2cSopenharmony_ci $(#[$filtered])* 90674522d2cSopenharmony_ci #[cfg $($cfgargs)*] 90774522d2cSopenharmony_ci $(? #[$rest $($restargs)*])* 90874522d2cSopenharmony_ci const $($item)* 90974522d2cSopenharmony_ci } 91074522d2cSopenharmony_ci }; 91174522d2cSopenharmony_ci ( 91274522d2cSopenharmony_ci $(#[$filtered:meta])* 91374522d2cSopenharmony_ci // $next != `cfg` 91474522d2cSopenharmony_ci ? #[$next:ident $($nextargs:tt)*] 91574522d2cSopenharmony_ci $(? #[$rest:ident $($restargs:tt)*])* 91674522d2cSopenharmony_ci const $($item:tt)* 91774522d2cSopenharmony_ci ) => { 91874522d2cSopenharmony_ci __impl_bitflags! { 91974522d2cSopenharmony_ci $(#[$filtered])* 92074522d2cSopenharmony_ci // $next filtered out 92174522d2cSopenharmony_ci $(? #[$rest $($restargs)*])* 92274522d2cSopenharmony_ci const $($item)* 92374522d2cSopenharmony_ci } 92474522d2cSopenharmony_ci }; 92574522d2cSopenharmony_ci ( 92674522d2cSopenharmony_ci $(#[$filtered:meta])* 92774522d2cSopenharmony_ci const $($item:tt)* 92874522d2cSopenharmony_ci ) => { 92974522d2cSopenharmony_ci $(#[$filtered])* 93074522d2cSopenharmony_ci const $($item)* 93174522d2cSopenharmony_ci }; 93274522d2cSopenharmony_ci} 93374522d2cSopenharmony_ci 93474522d2cSopenharmony_ci#[cfg(feature = "example_generated")] 93574522d2cSopenharmony_cipub mod example_generated; 93674522d2cSopenharmony_ci 93774522d2cSopenharmony_ci#[cfg(test)] 93874522d2cSopenharmony_cimod tests { 93974522d2cSopenharmony_ci use std::collections::hash_map::DefaultHasher; 94074522d2cSopenharmony_ci use std::hash::{Hash, Hasher}; 94174522d2cSopenharmony_ci 94274522d2cSopenharmony_ci bitflags! { 94374522d2cSopenharmony_ci #[doc = "> The first principle is that you must not fool yourself — and"] 94474522d2cSopenharmony_ci #[doc = "> you are the easiest person to fool."] 94574522d2cSopenharmony_ci #[doc = "> "] 94674522d2cSopenharmony_ci #[doc = "> - Richard Feynman"] 94774522d2cSopenharmony_ci #[derive(Default)] 94874522d2cSopenharmony_ci struct Flags: u32 { 94974522d2cSopenharmony_ci const A = 0b00000001; 95074522d2cSopenharmony_ci #[doc = "<pcwalton> macros are way better at generating code than trans is"] 95174522d2cSopenharmony_ci const B = 0b00000010; 95274522d2cSopenharmony_ci const C = 0b00000100; 95374522d2cSopenharmony_ci #[doc = "* cmr bed"] 95474522d2cSopenharmony_ci #[doc = "* strcat table"] 95574522d2cSopenharmony_ci #[doc = "<strcat> wait what?"] 95674522d2cSopenharmony_ci const ABC = Self::A.bits | Self::B.bits | Self::C.bits; 95774522d2cSopenharmony_ci } 95874522d2cSopenharmony_ci 95974522d2cSopenharmony_ci struct _CfgFlags: u32 { 96074522d2cSopenharmony_ci #[cfg(unix)] 96174522d2cSopenharmony_ci const _CFG_A = 0b01; 96274522d2cSopenharmony_ci #[cfg(windows)] 96374522d2cSopenharmony_ci const _CFG_B = 0b01; 96474522d2cSopenharmony_ci #[cfg(unix)] 96574522d2cSopenharmony_ci const _CFG_C = Self::_CFG_A.bits | 0b10; 96674522d2cSopenharmony_ci } 96774522d2cSopenharmony_ci 96874522d2cSopenharmony_ci struct AnotherSetOfFlags: i8 { 96974522d2cSopenharmony_ci const ANOTHER_FLAG = -1_i8; 97074522d2cSopenharmony_ci } 97174522d2cSopenharmony_ci 97274522d2cSopenharmony_ci struct LongFlags: u32 { 97374522d2cSopenharmony_ci const LONG_A = 0b1111111111111111; 97474522d2cSopenharmony_ci } 97574522d2cSopenharmony_ci } 97674522d2cSopenharmony_ci 97774522d2cSopenharmony_ci bitflags! { 97874522d2cSopenharmony_ci struct EmptyFlags: u32 { 97974522d2cSopenharmony_ci } 98074522d2cSopenharmony_ci } 98174522d2cSopenharmony_ci 98274522d2cSopenharmony_ci #[test] 98374522d2cSopenharmony_ci fn test_bits() { 98474522d2cSopenharmony_ci assert_eq!(Flags::empty().bits(), 0b00000000); 98574522d2cSopenharmony_ci assert_eq!(Flags::A.bits(), 0b00000001); 98674522d2cSopenharmony_ci assert_eq!(Flags::ABC.bits(), 0b00000111); 98774522d2cSopenharmony_ci 98874522d2cSopenharmony_ci assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00); 98974522d2cSopenharmony_ci assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8); 99074522d2cSopenharmony_ci 99174522d2cSopenharmony_ci assert_eq!(EmptyFlags::empty().bits(), 0b00000000); 99274522d2cSopenharmony_ci } 99374522d2cSopenharmony_ci 99474522d2cSopenharmony_ci #[test] 99574522d2cSopenharmony_ci fn test_from_bits() { 99674522d2cSopenharmony_ci assert_eq!(Flags::from_bits(0), Some(Flags::empty())); 99774522d2cSopenharmony_ci assert_eq!(Flags::from_bits(0b1), Some(Flags::A)); 99874522d2cSopenharmony_ci assert_eq!(Flags::from_bits(0b10), Some(Flags::B)); 99974522d2cSopenharmony_ci assert_eq!(Flags::from_bits(0b11), Some(Flags::A | Flags::B)); 100074522d2cSopenharmony_ci assert_eq!(Flags::from_bits(0b1000), None); 100174522d2cSopenharmony_ci 100274522d2cSopenharmony_ci assert_eq!( 100374522d2cSopenharmony_ci AnotherSetOfFlags::from_bits(!0_i8), 100474522d2cSopenharmony_ci Some(AnotherSetOfFlags::ANOTHER_FLAG) 100574522d2cSopenharmony_ci ); 100674522d2cSopenharmony_ci 100774522d2cSopenharmony_ci assert_eq!(EmptyFlags::from_bits(0), Some(EmptyFlags::empty())); 100874522d2cSopenharmony_ci assert_eq!(EmptyFlags::from_bits(0b1), None); 100974522d2cSopenharmony_ci } 101074522d2cSopenharmony_ci 101174522d2cSopenharmony_ci #[test] 101274522d2cSopenharmony_ci fn test_from_bits_truncate() { 101374522d2cSopenharmony_ci assert_eq!(Flags::from_bits_truncate(0), Flags::empty()); 101474522d2cSopenharmony_ci assert_eq!(Flags::from_bits_truncate(0b1), Flags::A); 101574522d2cSopenharmony_ci assert_eq!(Flags::from_bits_truncate(0b10), Flags::B); 101674522d2cSopenharmony_ci assert_eq!(Flags::from_bits_truncate(0b11), (Flags::A | Flags::B)); 101774522d2cSopenharmony_ci assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty()); 101874522d2cSopenharmony_ci assert_eq!(Flags::from_bits_truncate(0b1001), Flags::A); 101974522d2cSopenharmony_ci 102074522d2cSopenharmony_ci assert_eq!( 102174522d2cSopenharmony_ci AnotherSetOfFlags::from_bits_truncate(0_i8), 102274522d2cSopenharmony_ci AnotherSetOfFlags::empty() 102374522d2cSopenharmony_ci ); 102474522d2cSopenharmony_ci 102574522d2cSopenharmony_ci assert_eq!(EmptyFlags::from_bits_truncate(0), EmptyFlags::empty()); 102674522d2cSopenharmony_ci assert_eq!(EmptyFlags::from_bits_truncate(0b1), EmptyFlags::empty()); 102774522d2cSopenharmony_ci } 102874522d2cSopenharmony_ci 102974522d2cSopenharmony_ci #[test] 103074522d2cSopenharmony_ci fn test_from_bits_unchecked() { 103174522d2cSopenharmony_ci let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; 103274522d2cSopenharmony_ci assert_eq!(unsafe { Flags::from_bits_unchecked(0) }, Flags::empty()); 103374522d2cSopenharmony_ci assert_eq!(unsafe { Flags::from_bits_unchecked(0b1) }, Flags::A); 103474522d2cSopenharmony_ci assert_eq!(unsafe { Flags::from_bits_unchecked(0b10) }, Flags::B); 103574522d2cSopenharmony_ci 103674522d2cSopenharmony_ci assert_eq!( 103774522d2cSopenharmony_ci unsafe { Flags::from_bits_unchecked(0b11) }, 103874522d2cSopenharmony_ci (Flags::A | Flags::B) 103974522d2cSopenharmony_ci ); 104074522d2cSopenharmony_ci assert_eq!( 104174522d2cSopenharmony_ci unsafe { Flags::from_bits_unchecked(0b1000) }, 104274522d2cSopenharmony_ci (extra | Flags::empty()) 104374522d2cSopenharmony_ci ); 104474522d2cSopenharmony_ci assert_eq!( 104574522d2cSopenharmony_ci unsafe { Flags::from_bits_unchecked(0b1001) }, 104674522d2cSopenharmony_ci (extra | Flags::A) 104774522d2cSopenharmony_ci ); 104874522d2cSopenharmony_ci 104974522d2cSopenharmony_ci let extra = unsafe { EmptyFlags::from_bits_unchecked(0b1000) }; 105074522d2cSopenharmony_ci assert_eq!( 105174522d2cSopenharmony_ci unsafe { EmptyFlags::from_bits_unchecked(0b1000) }, 105274522d2cSopenharmony_ci (extra | EmptyFlags::empty()) 105374522d2cSopenharmony_ci ); 105474522d2cSopenharmony_ci } 105574522d2cSopenharmony_ci 105674522d2cSopenharmony_ci #[test] 105774522d2cSopenharmony_ci fn test_is_empty() { 105874522d2cSopenharmony_ci assert!(Flags::empty().is_empty()); 105974522d2cSopenharmony_ci assert!(!Flags::A.is_empty()); 106074522d2cSopenharmony_ci assert!(!Flags::ABC.is_empty()); 106174522d2cSopenharmony_ci 106274522d2cSopenharmony_ci assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty()); 106374522d2cSopenharmony_ci 106474522d2cSopenharmony_ci assert!(EmptyFlags::empty().is_empty()); 106574522d2cSopenharmony_ci assert!(EmptyFlags::all().is_empty()); 106674522d2cSopenharmony_ci } 106774522d2cSopenharmony_ci 106874522d2cSopenharmony_ci #[test] 106974522d2cSopenharmony_ci fn test_is_all() { 107074522d2cSopenharmony_ci assert!(Flags::all().is_all()); 107174522d2cSopenharmony_ci assert!(!Flags::A.is_all()); 107274522d2cSopenharmony_ci assert!(Flags::ABC.is_all()); 107374522d2cSopenharmony_ci 107474522d2cSopenharmony_ci let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; 107574522d2cSopenharmony_ci assert!(!extra.is_all()); 107674522d2cSopenharmony_ci assert!(!(Flags::A | extra).is_all()); 107774522d2cSopenharmony_ci assert!((Flags::ABC | extra).is_all()); 107874522d2cSopenharmony_ci 107974522d2cSopenharmony_ci assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all()); 108074522d2cSopenharmony_ci 108174522d2cSopenharmony_ci assert!(EmptyFlags::all().is_all()); 108274522d2cSopenharmony_ci assert!(EmptyFlags::empty().is_all()); 108374522d2cSopenharmony_ci } 108474522d2cSopenharmony_ci 108574522d2cSopenharmony_ci #[test] 108674522d2cSopenharmony_ci fn test_two_empties_do_not_intersect() { 108774522d2cSopenharmony_ci let e1 = Flags::empty(); 108874522d2cSopenharmony_ci let e2 = Flags::empty(); 108974522d2cSopenharmony_ci assert!(!e1.intersects(e2)); 109074522d2cSopenharmony_ci 109174522d2cSopenharmony_ci assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG)); 109274522d2cSopenharmony_ci } 109374522d2cSopenharmony_ci 109474522d2cSopenharmony_ci #[test] 109574522d2cSopenharmony_ci fn test_empty_does_not_intersect_with_full() { 109674522d2cSopenharmony_ci let e1 = Flags::empty(); 109774522d2cSopenharmony_ci let e2 = Flags::ABC; 109874522d2cSopenharmony_ci assert!(!e1.intersects(e2)); 109974522d2cSopenharmony_ci } 110074522d2cSopenharmony_ci 110174522d2cSopenharmony_ci #[test] 110274522d2cSopenharmony_ci fn test_disjoint_intersects() { 110374522d2cSopenharmony_ci let e1 = Flags::A; 110474522d2cSopenharmony_ci let e2 = Flags::B; 110574522d2cSopenharmony_ci assert!(!e1.intersects(e2)); 110674522d2cSopenharmony_ci } 110774522d2cSopenharmony_ci 110874522d2cSopenharmony_ci #[test] 110974522d2cSopenharmony_ci fn test_overlapping_intersects() { 111074522d2cSopenharmony_ci let e1 = Flags::A; 111174522d2cSopenharmony_ci let e2 = Flags::A | Flags::B; 111274522d2cSopenharmony_ci assert!(e1.intersects(e2)); 111374522d2cSopenharmony_ci } 111474522d2cSopenharmony_ci 111574522d2cSopenharmony_ci #[test] 111674522d2cSopenharmony_ci fn test_contains() { 111774522d2cSopenharmony_ci let e1 = Flags::A; 111874522d2cSopenharmony_ci let e2 = Flags::A | Flags::B; 111974522d2cSopenharmony_ci assert!(!e1.contains(e2)); 112074522d2cSopenharmony_ci assert!(e2.contains(e1)); 112174522d2cSopenharmony_ci assert!(Flags::ABC.contains(e2)); 112274522d2cSopenharmony_ci 112374522d2cSopenharmony_ci assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG)); 112474522d2cSopenharmony_ci 112574522d2cSopenharmony_ci assert!(EmptyFlags::empty().contains(EmptyFlags::empty())); 112674522d2cSopenharmony_ci } 112774522d2cSopenharmony_ci 112874522d2cSopenharmony_ci #[test] 112974522d2cSopenharmony_ci fn test_insert() { 113074522d2cSopenharmony_ci let mut e1 = Flags::A; 113174522d2cSopenharmony_ci let e2 = Flags::A | Flags::B; 113274522d2cSopenharmony_ci e1.insert(e2); 113374522d2cSopenharmony_ci assert_eq!(e1, e2); 113474522d2cSopenharmony_ci 113574522d2cSopenharmony_ci let mut e3 = AnotherSetOfFlags::empty(); 113674522d2cSopenharmony_ci e3.insert(AnotherSetOfFlags::ANOTHER_FLAG); 113774522d2cSopenharmony_ci assert_eq!(e3, AnotherSetOfFlags::ANOTHER_FLAG); 113874522d2cSopenharmony_ci } 113974522d2cSopenharmony_ci 114074522d2cSopenharmony_ci #[test] 114174522d2cSopenharmony_ci fn test_remove() { 114274522d2cSopenharmony_ci let mut e1 = Flags::A | Flags::B; 114374522d2cSopenharmony_ci let e2 = Flags::A | Flags::C; 114474522d2cSopenharmony_ci e1.remove(e2); 114574522d2cSopenharmony_ci assert_eq!(e1, Flags::B); 114674522d2cSopenharmony_ci 114774522d2cSopenharmony_ci let mut e3 = AnotherSetOfFlags::ANOTHER_FLAG; 114874522d2cSopenharmony_ci e3.remove(AnotherSetOfFlags::ANOTHER_FLAG); 114974522d2cSopenharmony_ci assert_eq!(e3, AnotherSetOfFlags::empty()); 115074522d2cSopenharmony_ci } 115174522d2cSopenharmony_ci 115274522d2cSopenharmony_ci #[test] 115374522d2cSopenharmony_ci fn test_operators() { 115474522d2cSopenharmony_ci let e1 = Flags::A | Flags::C; 115574522d2cSopenharmony_ci let e2 = Flags::B | Flags::C; 115674522d2cSopenharmony_ci assert_eq!((e1 | e2), Flags::ABC); // union 115774522d2cSopenharmony_ci assert_eq!((e1 & e2), Flags::C); // intersection 115874522d2cSopenharmony_ci assert_eq!((e1 - e2), Flags::A); // set difference 115974522d2cSopenharmony_ci assert_eq!(!e2, Flags::A); // set complement 116074522d2cSopenharmony_ci assert_eq!(e1 ^ e2, Flags::A | Flags::B); // toggle 116174522d2cSopenharmony_ci let mut e3 = e1; 116274522d2cSopenharmony_ci e3.toggle(e2); 116374522d2cSopenharmony_ci assert_eq!(e3, Flags::A | Flags::B); 116474522d2cSopenharmony_ci 116574522d2cSopenharmony_ci let mut m4 = AnotherSetOfFlags::empty(); 116674522d2cSopenharmony_ci m4.toggle(AnotherSetOfFlags::empty()); 116774522d2cSopenharmony_ci assert_eq!(m4, AnotherSetOfFlags::empty()); 116874522d2cSopenharmony_ci } 116974522d2cSopenharmony_ci 117074522d2cSopenharmony_ci #[test] 117174522d2cSopenharmony_ci fn test_operators_unchecked() { 117274522d2cSopenharmony_ci let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; 117374522d2cSopenharmony_ci let e1 = Flags::A | Flags::C | extra; 117474522d2cSopenharmony_ci let e2 = Flags::B | Flags::C; 117574522d2cSopenharmony_ci assert_eq!((e1 | e2), (Flags::ABC | extra)); // union 117674522d2cSopenharmony_ci assert_eq!((e1 & e2), Flags::C); // intersection 117774522d2cSopenharmony_ci assert_eq!((e1 - e2), (Flags::A | extra)); // set difference 117874522d2cSopenharmony_ci assert_eq!(!e2, Flags::A); // set complement 117974522d2cSopenharmony_ci assert_eq!(!e1, Flags::B); // set complement 118074522d2cSopenharmony_ci assert_eq!(e1 ^ e2, Flags::A | Flags::B | extra); // toggle 118174522d2cSopenharmony_ci let mut e3 = e1; 118274522d2cSopenharmony_ci e3.toggle(e2); 118374522d2cSopenharmony_ci assert_eq!(e3, Flags::A | Flags::B | extra); 118474522d2cSopenharmony_ci } 118574522d2cSopenharmony_ci 118674522d2cSopenharmony_ci #[test] 118774522d2cSopenharmony_ci fn test_set_ops_basic() { 118874522d2cSopenharmony_ci let ab = Flags::A.union(Flags::B); 118974522d2cSopenharmony_ci let ac = Flags::A.union(Flags::C); 119074522d2cSopenharmony_ci let bc = Flags::B.union(Flags::C); 119174522d2cSopenharmony_ci assert_eq!(ab.bits, 0b011); 119274522d2cSopenharmony_ci assert_eq!(bc.bits, 0b110); 119374522d2cSopenharmony_ci assert_eq!(ac.bits, 0b101); 119474522d2cSopenharmony_ci 119574522d2cSopenharmony_ci assert_eq!(ab, Flags::B.union(Flags::A)); 119674522d2cSopenharmony_ci assert_eq!(ac, Flags::C.union(Flags::A)); 119774522d2cSopenharmony_ci assert_eq!(bc, Flags::C.union(Flags::B)); 119874522d2cSopenharmony_ci 119974522d2cSopenharmony_ci assert_eq!(ac, Flags::A | Flags::C); 120074522d2cSopenharmony_ci assert_eq!(bc, Flags::B | Flags::C); 120174522d2cSopenharmony_ci assert_eq!(ab.union(bc), Flags::ABC); 120274522d2cSopenharmony_ci 120374522d2cSopenharmony_ci assert_eq!(ac, Flags::A | Flags::C); 120474522d2cSopenharmony_ci assert_eq!(bc, Flags::B | Flags::C); 120574522d2cSopenharmony_ci 120674522d2cSopenharmony_ci assert_eq!(ac.union(bc), ac | bc); 120774522d2cSopenharmony_ci assert_eq!(ac.union(bc), Flags::ABC); 120874522d2cSopenharmony_ci assert_eq!(bc.union(ac), Flags::ABC); 120974522d2cSopenharmony_ci 121074522d2cSopenharmony_ci assert_eq!(ac.intersection(bc), ac & bc); 121174522d2cSopenharmony_ci assert_eq!(ac.intersection(bc), Flags::C); 121274522d2cSopenharmony_ci assert_eq!(bc.intersection(ac), Flags::C); 121374522d2cSopenharmony_ci 121474522d2cSopenharmony_ci assert_eq!(ac.difference(bc), ac - bc); 121574522d2cSopenharmony_ci assert_eq!(bc.difference(ac), bc - ac); 121674522d2cSopenharmony_ci assert_eq!(ac.difference(bc), Flags::A); 121774522d2cSopenharmony_ci assert_eq!(bc.difference(ac), Flags::B); 121874522d2cSopenharmony_ci 121974522d2cSopenharmony_ci assert_eq!(bc.complement(), !bc); 122074522d2cSopenharmony_ci assert_eq!(bc.complement(), Flags::A); 122174522d2cSopenharmony_ci assert_eq!(ac.symmetric_difference(bc), Flags::A.union(Flags::B)); 122274522d2cSopenharmony_ci assert_eq!(bc.symmetric_difference(ac), Flags::A.union(Flags::B)); 122374522d2cSopenharmony_ci } 122474522d2cSopenharmony_ci 122574522d2cSopenharmony_ci #[test] 122674522d2cSopenharmony_ci fn test_set_ops_const() { 122774522d2cSopenharmony_ci // These just test that these compile and don't cause use-site panics 122874522d2cSopenharmony_ci // (would be possible if we had some sort of UB) 122974522d2cSopenharmony_ci const INTERSECT: Flags = Flags::all().intersection(Flags::C); 123074522d2cSopenharmony_ci const UNION: Flags = Flags::A.union(Flags::C); 123174522d2cSopenharmony_ci const DIFFERENCE: Flags = Flags::all().difference(Flags::A); 123274522d2cSopenharmony_ci const COMPLEMENT: Flags = Flags::C.complement(); 123374522d2cSopenharmony_ci const SYM_DIFFERENCE: Flags = UNION.symmetric_difference(DIFFERENCE); 123474522d2cSopenharmony_ci assert_eq!(INTERSECT, Flags::C); 123574522d2cSopenharmony_ci assert_eq!(UNION, Flags::A | Flags::C); 123674522d2cSopenharmony_ci assert_eq!(DIFFERENCE, Flags::all() - Flags::A); 123774522d2cSopenharmony_ci assert_eq!(COMPLEMENT, !Flags::C); 123874522d2cSopenharmony_ci assert_eq!(SYM_DIFFERENCE, (Flags::A | Flags::C) ^ (Flags::all() - Flags::A)); 123974522d2cSopenharmony_ci } 124074522d2cSopenharmony_ci 124174522d2cSopenharmony_ci #[test] 124274522d2cSopenharmony_ci fn test_set_ops_unchecked() { 124374522d2cSopenharmony_ci let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; 124474522d2cSopenharmony_ci let e1 = Flags::A.union(Flags::C).union(extra); 124574522d2cSopenharmony_ci let e2 = Flags::B.union(Flags::C); 124674522d2cSopenharmony_ci assert_eq!(e1.bits, 0b1101); 124774522d2cSopenharmony_ci assert_eq!(e1.union(e2), (Flags::ABC | extra)); 124874522d2cSopenharmony_ci assert_eq!(e1.intersection(e2), Flags::C); 124974522d2cSopenharmony_ci assert_eq!(e1.difference(e2), Flags::A | extra); 125074522d2cSopenharmony_ci assert_eq!(e2.difference(e1), Flags::B); 125174522d2cSopenharmony_ci assert_eq!(e2.complement(), Flags::A); 125274522d2cSopenharmony_ci assert_eq!(e1.complement(), Flags::B); 125374522d2cSopenharmony_ci assert_eq!(e1.symmetric_difference(e2), Flags::A | Flags::B | extra); // toggle 125474522d2cSopenharmony_ci } 125574522d2cSopenharmony_ci 125674522d2cSopenharmony_ci #[test] 125774522d2cSopenharmony_ci fn test_set_ops_exhaustive() { 125874522d2cSopenharmony_ci // Define a flag that contains gaps to help exercise edge-cases, 125974522d2cSopenharmony_ci // especially around "unknown" flags (e.g. ones outside of `all()` 126074522d2cSopenharmony_ci // `from_bits_unchecked`). 126174522d2cSopenharmony_ci // - when lhs and rhs both have different sets of unknown flags. 126274522d2cSopenharmony_ci // - unknown flags at both ends, and in the middle 126374522d2cSopenharmony_ci // - cases with "gaps". 126474522d2cSopenharmony_ci bitflags! { 126574522d2cSopenharmony_ci struct Test: u16 { 126674522d2cSopenharmony_ci // Intentionally no `A` 126774522d2cSopenharmony_ci const B = 0b000000010; 126874522d2cSopenharmony_ci // Intentionally no `C` 126974522d2cSopenharmony_ci const D = 0b000001000; 127074522d2cSopenharmony_ci const E = 0b000010000; 127174522d2cSopenharmony_ci const F = 0b000100000; 127274522d2cSopenharmony_ci const G = 0b001000000; 127374522d2cSopenharmony_ci // Intentionally no `H` 127474522d2cSopenharmony_ci const I = 0b100000000; 127574522d2cSopenharmony_ci } 127674522d2cSopenharmony_ci } 127774522d2cSopenharmony_ci let iter_test_flags = 127874522d2cSopenharmony_ci || (0..=0b111_1111_1111).map(|bits| unsafe { Test::from_bits_unchecked(bits) }); 127974522d2cSopenharmony_ci 128074522d2cSopenharmony_ci for a in iter_test_flags() { 128174522d2cSopenharmony_ci assert_eq!( 128274522d2cSopenharmony_ci a.complement(), 128374522d2cSopenharmony_ci Test::from_bits_truncate(!a.bits), 128474522d2cSopenharmony_ci "wrong result: !({:?})", 128574522d2cSopenharmony_ci a, 128674522d2cSopenharmony_ci ); 128774522d2cSopenharmony_ci assert_eq!(a.complement(), !a, "named != op: !({:?})", a); 128874522d2cSopenharmony_ci for b in iter_test_flags() { 128974522d2cSopenharmony_ci // Check that the named operations produce the expected bitwise 129074522d2cSopenharmony_ci // values. 129174522d2cSopenharmony_ci assert_eq!( 129274522d2cSopenharmony_ci a.union(b).bits, 129374522d2cSopenharmony_ci a.bits | b.bits, 129474522d2cSopenharmony_ci "wrong result: `{:?}` | `{:?}`", 129574522d2cSopenharmony_ci a, 129674522d2cSopenharmony_ci b, 129774522d2cSopenharmony_ci ); 129874522d2cSopenharmony_ci assert_eq!( 129974522d2cSopenharmony_ci a.intersection(b).bits, 130074522d2cSopenharmony_ci a.bits & b.bits, 130174522d2cSopenharmony_ci "wrong result: `{:?}` & `{:?}`", 130274522d2cSopenharmony_ci a, 130374522d2cSopenharmony_ci b, 130474522d2cSopenharmony_ci ); 130574522d2cSopenharmony_ci assert_eq!( 130674522d2cSopenharmony_ci a.symmetric_difference(b).bits, 130774522d2cSopenharmony_ci a.bits ^ b.bits, 130874522d2cSopenharmony_ci "wrong result: `{:?}` ^ `{:?}`", 130974522d2cSopenharmony_ci a, 131074522d2cSopenharmony_ci b, 131174522d2cSopenharmony_ci ); 131274522d2cSopenharmony_ci assert_eq!( 131374522d2cSopenharmony_ci a.difference(b).bits, 131474522d2cSopenharmony_ci a.bits & !b.bits, 131574522d2cSopenharmony_ci "wrong result: `{:?}` - `{:?}`", 131674522d2cSopenharmony_ci a, 131774522d2cSopenharmony_ci b, 131874522d2cSopenharmony_ci ); 131974522d2cSopenharmony_ci // Note: Difference is checked as both `a - b` and `b - a` 132074522d2cSopenharmony_ci assert_eq!( 132174522d2cSopenharmony_ci b.difference(a).bits, 132274522d2cSopenharmony_ci b.bits & !a.bits, 132374522d2cSopenharmony_ci "wrong result: `{:?}` - `{:?}`", 132474522d2cSopenharmony_ci b, 132574522d2cSopenharmony_ci a, 132674522d2cSopenharmony_ci ); 132774522d2cSopenharmony_ci // Check that the named set operations are equivalent to the 132874522d2cSopenharmony_ci // bitwise equivalents 132974522d2cSopenharmony_ci assert_eq!(a.union(b), a | b, "named != op: `{:?}` | `{:?}`", a, b,); 133074522d2cSopenharmony_ci assert_eq!( 133174522d2cSopenharmony_ci a.intersection(b), 133274522d2cSopenharmony_ci a & b, 133374522d2cSopenharmony_ci "named != op: `{:?}` & `{:?}`", 133474522d2cSopenharmony_ci a, 133574522d2cSopenharmony_ci b, 133674522d2cSopenharmony_ci ); 133774522d2cSopenharmony_ci assert_eq!( 133874522d2cSopenharmony_ci a.symmetric_difference(b), 133974522d2cSopenharmony_ci a ^ b, 134074522d2cSopenharmony_ci "named != op: `{:?}` ^ `{:?}`", 134174522d2cSopenharmony_ci a, 134274522d2cSopenharmony_ci b, 134374522d2cSopenharmony_ci ); 134474522d2cSopenharmony_ci assert_eq!(a.difference(b), a - b, "named != op: `{:?}` - `{:?}`", a, b,); 134574522d2cSopenharmony_ci // Note: Difference is checked as both `a - b` and `b - a` 134674522d2cSopenharmony_ci assert_eq!(b.difference(a), b - a, "named != op: `{:?}` - `{:?}`", b, a,); 134774522d2cSopenharmony_ci // Verify that the operations which should be symmetric are 134874522d2cSopenharmony_ci // actually symmetric. 134974522d2cSopenharmony_ci assert_eq!(a.union(b), b.union(a), "asymmetry: `{:?}` | `{:?}`", a, b,); 135074522d2cSopenharmony_ci assert_eq!( 135174522d2cSopenharmony_ci a.intersection(b), 135274522d2cSopenharmony_ci b.intersection(a), 135374522d2cSopenharmony_ci "asymmetry: `{:?}` & `{:?}`", 135474522d2cSopenharmony_ci a, 135574522d2cSopenharmony_ci b, 135674522d2cSopenharmony_ci ); 135774522d2cSopenharmony_ci assert_eq!( 135874522d2cSopenharmony_ci a.symmetric_difference(b), 135974522d2cSopenharmony_ci b.symmetric_difference(a), 136074522d2cSopenharmony_ci "asymmetry: `{:?}` ^ `{:?}`", 136174522d2cSopenharmony_ci a, 136274522d2cSopenharmony_ci b, 136374522d2cSopenharmony_ci ); 136474522d2cSopenharmony_ci } 136574522d2cSopenharmony_ci } 136674522d2cSopenharmony_ci } 136774522d2cSopenharmony_ci 136874522d2cSopenharmony_ci #[test] 136974522d2cSopenharmony_ci fn test_set() { 137074522d2cSopenharmony_ci let mut e1 = Flags::A | Flags::C; 137174522d2cSopenharmony_ci e1.set(Flags::B, true); 137274522d2cSopenharmony_ci e1.set(Flags::C, false); 137374522d2cSopenharmony_ci 137474522d2cSopenharmony_ci assert_eq!(e1, Flags::A | Flags::B); 137574522d2cSopenharmony_ci } 137674522d2cSopenharmony_ci 137774522d2cSopenharmony_ci #[test] 137874522d2cSopenharmony_ci fn test_assignment_operators() { 137974522d2cSopenharmony_ci let mut m1 = Flags::empty(); 138074522d2cSopenharmony_ci let e1 = Flags::A | Flags::C; 138174522d2cSopenharmony_ci // union 138274522d2cSopenharmony_ci m1 |= Flags::A; 138374522d2cSopenharmony_ci assert_eq!(m1, Flags::A); 138474522d2cSopenharmony_ci // intersection 138574522d2cSopenharmony_ci m1 &= e1; 138674522d2cSopenharmony_ci assert_eq!(m1, Flags::A); 138774522d2cSopenharmony_ci // set difference 138874522d2cSopenharmony_ci m1 -= m1; 138974522d2cSopenharmony_ci assert_eq!(m1, Flags::empty()); 139074522d2cSopenharmony_ci // toggle 139174522d2cSopenharmony_ci m1 ^= e1; 139274522d2cSopenharmony_ci assert_eq!(m1, e1); 139374522d2cSopenharmony_ci } 139474522d2cSopenharmony_ci 139574522d2cSopenharmony_ci #[test] 139674522d2cSopenharmony_ci fn test_const_fn() { 139774522d2cSopenharmony_ci const _M1: Flags = Flags::empty(); 139874522d2cSopenharmony_ci 139974522d2cSopenharmony_ci const M2: Flags = Flags::A; 140074522d2cSopenharmony_ci assert_eq!(M2, Flags::A); 140174522d2cSopenharmony_ci 140274522d2cSopenharmony_ci const M3: Flags = Flags::C; 140374522d2cSopenharmony_ci assert_eq!(M3, Flags::C); 140474522d2cSopenharmony_ci } 140574522d2cSopenharmony_ci 140674522d2cSopenharmony_ci #[test] 140774522d2cSopenharmony_ci fn test_extend() { 140874522d2cSopenharmony_ci let mut flags; 140974522d2cSopenharmony_ci 141074522d2cSopenharmony_ci flags = Flags::empty(); 141174522d2cSopenharmony_ci flags.extend([].iter().cloned()); 141274522d2cSopenharmony_ci assert_eq!(flags, Flags::empty()); 141374522d2cSopenharmony_ci 141474522d2cSopenharmony_ci flags = Flags::empty(); 141574522d2cSopenharmony_ci flags.extend([Flags::A, Flags::B].iter().cloned()); 141674522d2cSopenharmony_ci assert_eq!(flags, Flags::A | Flags::B); 141774522d2cSopenharmony_ci 141874522d2cSopenharmony_ci flags = Flags::A; 141974522d2cSopenharmony_ci flags.extend([Flags::A, Flags::B].iter().cloned()); 142074522d2cSopenharmony_ci assert_eq!(flags, Flags::A | Flags::B); 142174522d2cSopenharmony_ci 142274522d2cSopenharmony_ci flags = Flags::B; 142374522d2cSopenharmony_ci flags.extend([Flags::A, Flags::ABC].iter().cloned()); 142474522d2cSopenharmony_ci assert_eq!(flags, Flags::ABC); 142574522d2cSopenharmony_ci } 142674522d2cSopenharmony_ci 142774522d2cSopenharmony_ci #[test] 142874522d2cSopenharmony_ci fn test_from_iterator() { 142974522d2cSopenharmony_ci assert_eq!([].iter().cloned().collect::<Flags>(), Flags::empty()); 143074522d2cSopenharmony_ci assert_eq!( 143174522d2cSopenharmony_ci [Flags::A, Flags::B].iter().cloned().collect::<Flags>(), 143274522d2cSopenharmony_ci Flags::A | Flags::B 143374522d2cSopenharmony_ci ); 143474522d2cSopenharmony_ci assert_eq!( 143574522d2cSopenharmony_ci [Flags::A, Flags::ABC].iter().cloned().collect::<Flags>(), 143674522d2cSopenharmony_ci Flags::ABC 143774522d2cSopenharmony_ci ); 143874522d2cSopenharmony_ci } 143974522d2cSopenharmony_ci 144074522d2cSopenharmony_ci #[test] 144174522d2cSopenharmony_ci fn test_lt() { 144274522d2cSopenharmony_ci let mut a = Flags::empty(); 144374522d2cSopenharmony_ci let mut b = Flags::empty(); 144474522d2cSopenharmony_ci 144574522d2cSopenharmony_ci assert!(!(a < b) && !(b < a)); 144674522d2cSopenharmony_ci b = Flags::B; 144774522d2cSopenharmony_ci assert!(a < b); 144874522d2cSopenharmony_ci a = Flags::C; 144974522d2cSopenharmony_ci assert!(!(a < b) && b < a); 145074522d2cSopenharmony_ci b = Flags::C | Flags::B; 145174522d2cSopenharmony_ci assert!(a < b); 145274522d2cSopenharmony_ci } 145374522d2cSopenharmony_ci 145474522d2cSopenharmony_ci #[test] 145574522d2cSopenharmony_ci fn test_ord() { 145674522d2cSopenharmony_ci let mut a = Flags::empty(); 145774522d2cSopenharmony_ci let mut b = Flags::empty(); 145874522d2cSopenharmony_ci 145974522d2cSopenharmony_ci assert!(a <= b && a >= b); 146074522d2cSopenharmony_ci a = Flags::A; 146174522d2cSopenharmony_ci assert!(a > b && a >= b); 146274522d2cSopenharmony_ci assert!(b < a && b <= a); 146374522d2cSopenharmony_ci b = Flags::B; 146474522d2cSopenharmony_ci assert!(b > a && b >= a); 146574522d2cSopenharmony_ci assert!(a < b && a <= b); 146674522d2cSopenharmony_ci } 146774522d2cSopenharmony_ci 146874522d2cSopenharmony_ci fn hash<T: Hash>(t: &T) -> u64 { 146974522d2cSopenharmony_ci let mut s = DefaultHasher::new(); 147074522d2cSopenharmony_ci t.hash(&mut s); 147174522d2cSopenharmony_ci s.finish() 147274522d2cSopenharmony_ci } 147374522d2cSopenharmony_ci 147474522d2cSopenharmony_ci #[test] 147574522d2cSopenharmony_ci fn test_hash() { 147674522d2cSopenharmony_ci let mut x = Flags::empty(); 147774522d2cSopenharmony_ci let mut y = Flags::empty(); 147874522d2cSopenharmony_ci assert_eq!(hash(&x), hash(&y)); 147974522d2cSopenharmony_ci x = Flags::all(); 148074522d2cSopenharmony_ci y = Flags::ABC; 148174522d2cSopenharmony_ci assert_eq!(hash(&x), hash(&y)); 148274522d2cSopenharmony_ci } 148374522d2cSopenharmony_ci 148474522d2cSopenharmony_ci #[test] 148574522d2cSopenharmony_ci fn test_default() { 148674522d2cSopenharmony_ci assert_eq!(Flags::empty(), Flags::default()); 148774522d2cSopenharmony_ci } 148874522d2cSopenharmony_ci 148974522d2cSopenharmony_ci #[test] 149074522d2cSopenharmony_ci fn test_debug() { 149174522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); 149274522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags::empty()), "(empty)"); 149374522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags::ABC), "A | B | C | ABC"); 149474522d2cSopenharmony_ci let extra = unsafe { Flags::from_bits_unchecked(0xb8) }; 149574522d2cSopenharmony_ci assert_eq!(format!("{:?}", extra), "0xb8"); 149674522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags::A | extra), "A | 0xb8"); 149774522d2cSopenharmony_ci 149874522d2cSopenharmony_ci assert_eq!( 149974522d2cSopenharmony_ci format!("{:?}", Flags::ABC | extra), 150074522d2cSopenharmony_ci "A | B | C | ABC | 0xb8" 150174522d2cSopenharmony_ci ); 150274522d2cSopenharmony_ci 150374522d2cSopenharmony_ci assert_eq!(format!("{:?}", EmptyFlags::empty()), "(empty)"); 150474522d2cSopenharmony_ci } 150574522d2cSopenharmony_ci 150674522d2cSopenharmony_ci #[test] 150774522d2cSopenharmony_ci fn test_binary() { 150874522d2cSopenharmony_ci assert_eq!(format!("{:b}", Flags::ABC), "111"); 150974522d2cSopenharmony_ci assert_eq!(format!("{:#b}", Flags::ABC), "0b111"); 151074522d2cSopenharmony_ci let extra = unsafe { Flags::from_bits_unchecked(0b1010000) }; 151174522d2cSopenharmony_ci assert_eq!(format!("{:b}", Flags::ABC | extra), "1010111"); 151274522d2cSopenharmony_ci assert_eq!(format!("{:#b}", Flags::ABC | extra), "0b1010111"); 151374522d2cSopenharmony_ci } 151474522d2cSopenharmony_ci 151574522d2cSopenharmony_ci #[test] 151674522d2cSopenharmony_ci fn test_octal() { 151774522d2cSopenharmony_ci assert_eq!(format!("{:o}", LongFlags::LONG_A), "177777"); 151874522d2cSopenharmony_ci assert_eq!(format!("{:#o}", LongFlags::LONG_A), "0o177777"); 151974522d2cSopenharmony_ci let extra = unsafe { LongFlags::from_bits_unchecked(0o5000000) }; 152074522d2cSopenharmony_ci assert_eq!(format!("{:o}", LongFlags::LONG_A | extra), "5177777"); 152174522d2cSopenharmony_ci assert_eq!(format!("{:#o}", LongFlags::LONG_A | extra), "0o5177777"); 152274522d2cSopenharmony_ci } 152374522d2cSopenharmony_ci 152474522d2cSopenharmony_ci #[test] 152574522d2cSopenharmony_ci fn test_lowerhex() { 152674522d2cSopenharmony_ci assert_eq!(format!("{:x}", LongFlags::LONG_A), "ffff"); 152774522d2cSopenharmony_ci assert_eq!(format!("{:#x}", LongFlags::LONG_A), "0xffff"); 152874522d2cSopenharmony_ci let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) }; 152974522d2cSopenharmony_ci assert_eq!(format!("{:x}", LongFlags::LONG_A | extra), "e0ffff"); 153074522d2cSopenharmony_ci assert_eq!(format!("{:#x}", LongFlags::LONG_A | extra), "0xe0ffff"); 153174522d2cSopenharmony_ci } 153274522d2cSopenharmony_ci 153374522d2cSopenharmony_ci #[test] 153474522d2cSopenharmony_ci fn test_upperhex() { 153574522d2cSopenharmony_ci assert_eq!(format!("{:X}", LongFlags::LONG_A), "FFFF"); 153674522d2cSopenharmony_ci assert_eq!(format!("{:#X}", LongFlags::LONG_A), "0xFFFF"); 153774522d2cSopenharmony_ci let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) }; 153874522d2cSopenharmony_ci assert_eq!(format!("{:X}", LongFlags::LONG_A | extra), "E0FFFF"); 153974522d2cSopenharmony_ci assert_eq!(format!("{:#X}", LongFlags::LONG_A | extra), "0xE0FFFF"); 154074522d2cSopenharmony_ci } 154174522d2cSopenharmony_ci 154274522d2cSopenharmony_ci mod submodule { 154374522d2cSopenharmony_ci bitflags! { 154474522d2cSopenharmony_ci pub struct PublicFlags: i8 { 154574522d2cSopenharmony_ci const X = 0; 154674522d2cSopenharmony_ci } 154774522d2cSopenharmony_ci 154874522d2cSopenharmony_ci struct PrivateFlags: i8 { 154974522d2cSopenharmony_ci const Y = 0; 155074522d2cSopenharmony_ci } 155174522d2cSopenharmony_ci } 155274522d2cSopenharmony_ci 155374522d2cSopenharmony_ci #[test] 155474522d2cSopenharmony_ci fn test_private() { 155574522d2cSopenharmony_ci let _ = PrivateFlags::Y; 155674522d2cSopenharmony_ci } 155774522d2cSopenharmony_ci } 155874522d2cSopenharmony_ci 155974522d2cSopenharmony_ci #[test] 156074522d2cSopenharmony_ci fn test_public() { 156174522d2cSopenharmony_ci let _ = submodule::PublicFlags::X; 156274522d2cSopenharmony_ci } 156374522d2cSopenharmony_ci 156474522d2cSopenharmony_ci mod t1 { 156574522d2cSopenharmony_ci mod foo { 156674522d2cSopenharmony_ci pub type Bar = i32; 156774522d2cSopenharmony_ci } 156874522d2cSopenharmony_ci 156974522d2cSopenharmony_ci bitflags! { 157074522d2cSopenharmony_ci /// baz 157174522d2cSopenharmony_ci struct Flags: foo::Bar { 157274522d2cSopenharmony_ci const A = 0b00000001; 157374522d2cSopenharmony_ci #[cfg(foo)] 157474522d2cSopenharmony_ci const B = 0b00000010; 157574522d2cSopenharmony_ci #[cfg(foo)] 157674522d2cSopenharmony_ci const C = 0b00000010; 157774522d2cSopenharmony_ci } 157874522d2cSopenharmony_ci } 157974522d2cSopenharmony_ci } 158074522d2cSopenharmony_ci 158174522d2cSopenharmony_ci #[test] 158274522d2cSopenharmony_ci fn test_in_function() { 158374522d2cSopenharmony_ci bitflags! { 158474522d2cSopenharmony_ci struct Flags: u8 { 158574522d2cSopenharmony_ci const A = 1; 158674522d2cSopenharmony_ci #[cfg(any())] // false 158774522d2cSopenharmony_ci const B = 2; 158874522d2cSopenharmony_ci } 158974522d2cSopenharmony_ci } 159074522d2cSopenharmony_ci assert_eq!(Flags::all(), Flags::A); 159174522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags::A), "A"); 159274522d2cSopenharmony_ci } 159374522d2cSopenharmony_ci 159474522d2cSopenharmony_ci #[test] 159574522d2cSopenharmony_ci fn test_deprecated() { 159674522d2cSopenharmony_ci bitflags! { 159774522d2cSopenharmony_ci pub struct TestFlags: u32 { 159874522d2cSopenharmony_ci #[deprecated(note = "Use something else.")] 159974522d2cSopenharmony_ci const ONE = 1; 160074522d2cSopenharmony_ci } 160174522d2cSopenharmony_ci } 160274522d2cSopenharmony_ci } 160374522d2cSopenharmony_ci 160474522d2cSopenharmony_ci #[test] 160574522d2cSopenharmony_ci fn test_pub_crate() { 160674522d2cSopenharmony_ci mod module { 160774522d2cSopenharmony_ci bitflags! { 160874522d2cSopenharmony_ci pub (crate) struct Test: u8 { 160974522d2cSopenharmony_ci const FOO = 1; 161074522d2cSopenharmony_ci } 161174522d2cSopenharmony_ci } 161274522d2cSopenharmony_ci } 161374522d2cSopenharmony_ci 161474522d2cSopenharmony_ci assert_eq!(module::Test::FOO.bits(), 1); 161574522d2cSopenharmony_ci } 161674522d2cSopenharmony_ci 161774522d2cSopenharmony_ci #[test] 161874522d2cSopenharmony_ci fn test_pub_in_module() { 161974522d2cSopenharmony_ci mod module { 162074522d2cSopenharmony_ci mod submodule { 162174522d2cSopenharmony_ci bitflags! { 162274522d2cSopenharmony_ci // `pub (in super)` means only the module `module` will 162374522d2cSopenharmony_ci // be able to access this. 162474522d2cSopenharmony_ci pub (in super) struct Test: u8 { 162574522d2cSopenharmony_ci const FOO = 1; 162674522d2cSopenharmony_ci } 162774522d2cSopenharmony_ci } 162874522d2cSopenharmony_ci } 162974522d2cSopenharmony_ci 163074522d2cSopenharmony_ci mod test { 163174522d2cSopenharmony_ci // Note: due to `pub (in super)`, 163274522d2cSopenharmony_ci // this cannot be accessed directly by the testing code. 163374522d2cSopenharmony_ci pub(super) fn value() -> u8 { 163474522d2cSopenharmony_ci super::submodule::Test::FOO.bits() 163574522d2cSopenharmony_ci } 163674522d2cSopenharmony_ci } 163774522d2cSopenharmony_ci 163874522d2cSopenharmony_ci pub fn value() -> u8 { 163974522d2cSopenharmony_ci test::value() 164074522d2cSopenharmony_ci } 164174522d2cSopenharmony_ci } 164274522d2cSopenharmony_ci 164374522d2cSopenharmony_ci assert_eq!(module::value(), 1) 164474522d2cSopenharmony_ci } 164574522d2cSopenharmony_ci 164674522d2cSopenharmony_ci #[test] 164774522d2cSopenharmony_ci fn test_zero_value_flags() { 164874522d2cSopenharmony_ci bitflags! { 164974522d2cSopenharmony_ci struct Flags: u32 { 165074522d2cSopenharmony_ci const NONE = 0b0; 165174522d2cSopenharmony_ci const SOME = 0b1; 165274522d2cSopenharmony_ci } 165374522d2cSopenharmony_ci } 165474522d2cSopenharmony_ci 165574522d2cSopenharmony_ci assert!(Flags::empty().contains(Flags::NONE)); 165674522d2cSopenharmony_ci assert!(Flags::SOME.contains(Flags::NONE)); 165774522d2cSopenharmony_ci assert!(Flags::NONE.is_empty()); 165874522d2cSopenharmony_ci 165974522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags::empty()), "NONE"); 166074522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags::SOME), "SOME"); 166174522d2cSopenharmony_ci } 166274522d2cSopenharmony_ci 166374522d2cSopenharmony_ci #[test] 166474522d2cSopenharmony_ci fn test_empty_bitflags() { 166574522d2cSopenharmony_ci bitflags! {} 166674522d2cSopenharmony_ci } 166774522d2cSopenharmony_ci 166874522d2cSopenharmony_ci #[test] 166974522d2cSopenharmony_ci fn test_u128_bitflags() { 167074522d2cSopenharmony_ci bitflags! { 167174522d2cSopenharmony_ci struct Flags128: u128 { 167274522d2cSopenharmony_ci const A = 0x0000_0000_0000_0000_0000_0000_0000_0001; 167374522d2cSopenharmony_ci const B = 0x0000_0000_0000_1000_0000_0000_0000_0000; 167474522d2cSopenharmony_ci const C = 0x8000_0000_0000_0000_0000_0000_0000_0000; 167574522d2cSopenharmony_ci const ABC = Self::A.bits | Self::B.bits | Self::C.bits; 167674522d2cSopenharmony_ci } 167774522d2cSopenharmony_ci } 167874522d2cSopenharmony_ci 167974522d2cSopenharmony_ci assert_eq!(Flags128::ABC, Flags128::A | Flags128::B | Flags128::C); 168074522d2cSopenharmony_ci assert_eq!(Flags128::A.bits, 0x0000_0000_0000_0000_0000_0000_0000_0001); 168174522d2cSopenharmony_ci assert_eq!(Flags128::B.bits, 0x0000_0000_0000_1000_0000_0000_0000_0000); 168274522d2cSopenharmony_ci assert_eq!(Flags128::C.bits, 0x8000_0000_0000_0000_0000_0000_0000_0000); 168374522d2cSopenharmony_ci assert_eq!( 168474522d2cSopenharmony_ci Flags128::ABC.bits, 168574522d2cSopenharmony_ci 0x8000_0000_0000_1000_0000_0000_0000_0001 168674522d2cSopenharmony_ci ); 168774522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags128::A), "A"); 168874522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags128::B), "B"); 168974522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags128::C), "C"); 169074522d2cSopenharmony_ci assert_eq!(format!("{:?}", Flags128::ABC), "A | B | C | ABC"); 169174522d2cSopenharmony_ci } 169274522d2cSopenharmony_ci 169374522d2cSopenharmony_ci #[test] 169474522d2cSopenharmony_ci fn test_serde_bitflags_serialize() { 169574522d2cSopenharmony_ci let flags = SerdeFlags::A | SerdeFlags::B; 169674522d2cSopenharmony_ci 169774522d2cSopenharmony_ci let serialized = serde_json::to_string(&flags).unwrap(); 169874522d2cSopenharmony_ci 169974522d2cSopenharmony_ci assert_eq!(serialized, r#"{"bits":3}"#); 170074522d2cSopenharmony_ci } 170174522d2cSopenharmony_ci 170274522d2cSopenharmony_ci #[test] 170374522d2cSopenharmony_ci fn test_serde_bitflags_deserialize() { 170474522d2cSopenharmony_ci let deserialized: SerdeFlags = serde_json::from_str(r#"{"bits":12}"#).unwrap(); 170574522d2cSopenharmony_ci 170674522d2cSopenharmony_ci let expected = SerdeFlags::C | SerdeFlags::D; 170774522d2cSopenharmony_ci 170874522d2cSopenharmony_ci assert_eq!(deserialized.bits, expected.bits); 170974522d2cSopenharmony_ci } 171074522d2cSopenharmony_ci 171174522d2cSopenharmony_ci #[test] 171274522d2cSopenharmony_ci fn test_serde_bitflags_roundtrip() { 171374522d2cSopenharmony_ci let flags = SerdeFlags::A | SerdeFlags::B; 171474522d2cSopenharmony_ci 171574522d2cSopenharmony_ci let deserialized: SerdeFlags = serde_json::from_str(&serde_json::to_string(&flags).unwrap()).unwrap(); 171674522d2cSopenharmony_ci 171774522d2cSopenharmony_ci assert_eq!(deserialized.bits, flags.bits); 171874522d2cSopenharmony_ci } 171974522d2cSopenharmony_ci 172074522d2cSopenharmony_ci bitflags! { 172174522d2cSopenharmony_ci #[derive(serde::Serialize, serde::Deserialize)] 172274522d2cSopenharmony_ci struct SerdeFlags: u32 { 172374522d2cSopenharmony_ci const A = 1; 172474522d2cSopenharmony_ci const B = 2; 172574522d2cSopenharmony_ci const C = 4; 172674522d2cSopenharmony_ci const D = 8; 172774522d2cSopenharmony_ci } 172874522d2cSopenharmony_ci } 172974522d2cSopenharmony_ci} 1730