Expand description
Generate types for C-style flags with ergonomic APIs.
Getting started
Add bitflags
to your Cargo.toml
:
[dependencies.bitflags]
version = "2.4.1"
Generating flags types
Use the bitflags
macro to generate flags types:
use bitflags::bitflags;
bitflags! {
pub struct Flags: u32 {
const A = 0b00000001;
const B = 0b00000010;
const C = 0b00000100;
}
}
See the docs for the bitflags
macro for the full syntax.
Also see the [example_generated
] module for an example of what the bitflags
macro generates for a flags type.
Externally defined flags
If you’re generating flags types for an external source, such as a C API, you can define
an extra unnamed flag as a mask of all bits the external source may ever set. Usually this would be all bits (!0
):
bitflags! {
pub struct Flags: u32 {
const A = 0b00000001;
const B = 0b00000010;
const C = 0b00000100;
// The source may set any bits
const _ = !0;
}
}
Why should you do this? Generated methods like all
and truncating operators like !
only consider
bits in defined flags. Adding an unnamed flag makes those methods consider additional bits,
without generating additional constants for them. It helps compatibility when the external source
may start setting additional bits at any time. The known and unknown bits
section has more details on this behavior.
Custom derives
You can derive some traits on generated flags types if you enable Cargo features. The following libraries are currently supported:
serde
: Support#[derive(Serialize, Deserialize)]
, using text for human-readable formats, and a raw number for binary formats.arbitrary
: Support#[derive(Arbitrary)]
, only generating flags values with known bits.bytemuck
: Support#[derive(Pod, Zeroable)]
, for casting between flags values and their underlying bits values.
You can also define your own flags type outside of the bitflags
macro and then use it to generate methods.
This can be useful if you need a custom #[derive]
attribute for a library that bitflags
doesn’t
natively support:
#[derive(SomeTrait)]
pub struct Flags(u32);
bitflags! {
impl Flags: u32 {
const A = 0b00000001;
const B = 0b00000010;
const C = 0b00000100;
}
}
Adding custom methods
The bitflags
macro supports attributes on generated flags types within the macro itself, while
impl
blocks can be added outside of it:
bitflags! {
// Attributes can be applied to flags types
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Flags: u32 {
const A = 0b00000001;
const B = 0b00000010;
const C = 0b00000100;
}
}
// Impl blocks can be added to flags types
impl Flags {
pub fn as_u64(&self) -> u64 {
self.bits() as u64
}
}
Working with flags values
Use generated constants and standard bitwise operators to interact with flags values:
// union
let ab = Flags::A | Flags::B;
// intersection
let a = ab & Flags::A;
// difference
let b = ab - Flags::A;
// complement
let c = !ab;
See the docs for the Flags
trait for more details on operators and how they behave.
Formatting and parsing
bitflags
defines a text format that can be used to convert any flags value to and from strings.
See the parser
module for more details.
Specification
The terminology and behavior of generated flags types is specified in the source repository. Details are repeated in these docs where appropriate, but is exhaustively listed in the spec. Some things are worth calling out explicitly here.
Flags types, flags values, flags
The spec and these docs use consistent terminology to refer to things in the bitflags domain:
- Bits type: A type that defines a fixed number of bits at specific locations.
- Flag: A set of bits in a bits type that may have a unique name.
- Flags type: A set of defined flags over a specific bits type.
- Flags value: An instance of a flags type using its specific bits value for storage.
bitflags! {
struct FlagsType: u8 {
// -- Bits type
// --------- Flags type
const A = 1;
// ----- Flag
}
}
let flag = FlagsType::A;
// ---- Flags value
Known and unknown bits
Any bits in a flag you define are called known bits. Any other bits are unknown bits. In the following flags type:
bitflags! {
struct Flags: u8 {
const A = 1;
const B = 1 << 1;
const C = 1 << 2;
}
}
The known bits are 0b0000_0111
and the unknown bits are 0b1111_1000
.
bitflags
doesn’t guarantee that a flags value will only ever have known bits set, but some operators
will unset any unknown bits they encounter. In a future version of bitflags
, all operators will
unset unknown bits.
If you’re using bitflags
for flags types defined externally, such as from C, you probably want all
bits to be considered known, in case that external source changes. You can do this using an unnamed
flag, as described in externally defined flags.
Zero-bit flags
Flags with no bits set should be avoided because they interact strangely with Flags::contains
and Flags::intersects
. A zero-bit flag is always contained, but is never intersected. The
names of zero-bit flags can be parsed, but are never formatted.
Multi-bit flags
Flags that set multiple bits should be avoided unless each bit is also in a single-bit flag. Take the following flags type as an example:
bitflags! {
struct Flags: u8 {
const A = 1;
const B = 1 | 1 << 1;
}
}
The result of Flags::A ^ Flags::B
is 0b0000_0010
, which doesn’t correspond to either
Flags::A
or Flags::B
even though it’s still a known bit.
Re-exports
pub use traits::BitFlags;
Deprecated
Modules
- Yield the bits of a source flags value in a set of contained flags values.
- Parsing flags from text.
Macros
- Generate a flags type.
Structs
- A defined flags value that may be named or unnamed.
Traits
- A bits type that can be used as storage for a flags type.
- A set of defined flags using a bits type as storage.