bitflags
generates flags enums with well-defined semantics and ergonomic end-user APIs.
You can use bitflags
to:
You can't use bitflags
to:
bitflags
allows access to the underlying bits type so arbitrary bits may be set.bitflags
only generates types where set bits denote the presence of some combination of flags.This section formally defines the terminology and semantics of bitflags
. It's organized so more fundamental concepts are introduced before those that build on them. It may be helpful to start from the bottom of the section and refer back up to concepts defined earlier.
Examples use bitflags
syntax with u8
as the bits type.
A type that defines a fixed number of bits at specific locations.
Bits types are typically fixed-width unsigned integers. For example, u8
is a bits type that defines 8 bits; bit-0 through bit-7.
An instance of a bits type where each bit may be set (1
) or unset (0
).
Some examples of bits values for the bits type u8
are:
0b0000_0000 0b1111_1111 0b1010_0101
Two bits values are equal if their bits are in the same configuration; set bits in one are set in the other, and unset bits in one are unset in the other.
Bits values define the bitwise operators and (&
), or (|
), exclusive-or (^
), and negation (!
) that apply to each of their bits.
A set of bits in a bits type that may have a unique name.
Bits are not required to be exclusive to a flag. Bits are not required to be contiguous.
The following is a flag for u8
with the name A
that includes bit-0:
const A = 0b0000_0001;
The following is a flag for u8
with the name B
that includes bit-0, and bit-5:
const B = 0b0010_0001;
A flag with a name.
The following is a named flag, where the name is A
:
const A = 0b0000_0001;
A flag without a name.
The following is an unnamed flag:
const _ = 0b0000_0001;
A flag with a set of zero bits.
The following is a zero-bit flag:
const ZERO = 0b0000_0000;
A flag with a set of one bit.
The following are single-bit flags:
const A = 0b0000_0001; const B = 0b0000_0010;
A flag with a set of more than one bit.
The following are multi-bit flags:
const A = 0b0000_0011; const B = 0b1111_1111;
A set of defined flags over a specific bits type.
A bit in any defined flag.
In the following flags type:
struct Flags { const A = 0b0000_0001; const B = 0b0000_0010; const C = 0b0000_0100; }
the known bits are:
0b0000_0111
A bit not in any defined flag.
In the following flags type:
struct Flags { const A = 0b0000_0001; const B = 0b0000_0010; const C = 0b0000_0100; }
the unknown bits are:
0b1111_1000
An instance of a flags type using its specific bits value for storage.
The flags value of a flag is one where each of its bits is set, and all others are unset.
Whether all set bits in a source flags value are also set in a target flags value.
Given the flags value:
0b0000_0011
the following flags values are contained:
0b0000_0000 0b0000_0010 0b0000_0001 0b0000_0011
but the following flags values are not contained:
0b0000_1000 0b0000_0110
Whether any set bits in a source flags value are also set in a target flags value.
Given the flags value:
0b0000_0011
the following flags intersect:
0b0000_0010 0b0000_0001 0b1111_1111
but the following flags values do not intersect:
0b0000_0000 0b1111_0000
Whether all bits in a flags value are unset.
The following flags value is empty:
0b0000_0000
The following flags values are not empty:
0b0000_0001 0b0110_0000
Whether all defined flags are contained in a flags value.
Given a flags type:
struct Flags { const A = 0b0000_0001; const B = 0b0000_0010; }
the following flags values all satisfy all:
0b0000_0011 0b1000_0011 0b1111_1111
Examples in this section all use the given flags type:
struct Flags { const A = 0b0000_0001; const B = 0b0000_0010; const C = 0b0000_1100; }
Unset all unknown bits in a flags value.
Given the flags value:
0b1111_1111
the result of truncation will be:
0b0000_1111
Truncating doesn't guarantee that a non-empty result will contain any defined flags. Given the following flags type:
struct Flags { const A = 0b0000_0101; }
and the following flags value:
0b0000_1110;
The result of truncation will be:
0b0000_0100;
which intersects the flag A
, but doesn't contain it.
This behavior is possible even when only operating with flags values containing defined flags. Given the following flags type:
struct Flags { const A = 0b0000_0101; const B = 0b0000_0001; }
The result of A ^ B
is 0b0000_0100
, which also doesn't contain any defined flag.
If all known bits are in the set of at least one defined single-bit flag, then all operations that produce non-empty results will always contain defined flags.
The bitwise or (|
) of the bits in two flags values.
The following are examples of the result of unioning flags values:
0b0000_0001 | 0b0000_0010 = 0b0000_0011 0b0000_0000 | 0b1111_1111 = 0b1111_1111
The bitwise and (&
) of the bits in two flags values.
The following are examples of the result of intersecting flags values:
0b0000_0001 & 0b0000_0010 = 0b0000_0000 0b1111_1100 & 0b1111_0111 = 0b1111_0100 0b1111_1111 & 0b1111_1111 = 0b1111_1111
The bitwise exclusive-or (^
) of the bits in two flags values.
The following are examples of the symmetric difference between two flags values:
0b0000_0001 ^ 0b0000_0010 = 0b0000_0011 0b0000_1111 ^ 0b0000_0011 = 0b0000_1100 0b1100_0000 ^ 0b0011_0000 = 0b1111_0000
The bitwise negation (!
) of the bits in a flags value, truncating the result.
The following are examples of the complement of a flags value:
!0b0000_0000 = 0b0000_1111 !0b0000_1111 = 0b0000_0000 !0b1111_1000 = 0b0000_0111
The bitwise union (|
) of the bits in one flags value and the bitwise negation (!
) of the bits in another.
This operation is not equivalent to the intersection of one flags value with the complement of another (&!
). The former will truncate the result, where difference will not.
The following are examples of the difference between two flags values:
0b0000_0001 & !0b0000_0010 = 0b0000_0001 0b0000_1101 & !0b0000_0011 = 0b0000_1100 0b1111_1111 & !0b0000_0001 = 0b1111_1110
Yield the bits of a source flags value in a set of contained flags values.
To be most useful, each yielded flags value should set exactly the bits of a defined flag contained in the source. Any known bits that aren't in the set of any contained flag should be yielded together as a final flags value.
Given the following flags type:
struct Flags { const A = 0b0000_0001; const B = 0b0000_0010; const AB = 0b0000_0011; }
and the following flags value:
0b0000_1111
When iterated it may yield a flags value for A
and B
, then a final flag with the unknown bits:
0b0000_0001 0b0000_0010 0b0000_1100
It may also yield a flags value for AB
, then a final flag with the unknown bits:
0b0000_0011 0b0000_1100
Given the following flags type:
struct Flags { const A = 0b0000_0011; }
and the following flags value:
0b0000_0001
When iterated it will still yield a flags value for the known bit 0b0000_0001
even though it doesn't contain a flag.
Format and parse a flags value as text using the following grammar:
|
*0x
([0-9a-fA-F])*Flags values can be formatted as Flags by iterating over them, formatting each yielded flags value as a Flag. Any yielded flags value that sets exactly the bits of a defined flag with a name should be formatted as a Name. Otherwise it must be formatted as a Hex Number.
Formatting and parsing supports three modes:
Text that is empty or whitespace is an empty flags value.
Given the following flags type:
struct Flags { const A = 0b0000_0001; const B = 0b0000_0010; const AB = 0b0000_0011; const C = 0b0000_1100; }
The following are examples of how flags values can be formatted using any mode:
0b0000_0000 = "" 0b0000_0001 = "A" 0b0000_0010 = "B" 0b0000_0011 = "A | B" 0b0000_0011 = "AB" 0b0000_1111 = "A | B | C"
Truncate mode will unset any unknown bits:
0b1000_0000 = "" 0b1111_1111 = "A | B | C" 0b0000_1000 = "0x8"
Retain mode will include any unknown bits as a final Flag:
0b1000_0000 = "0x80" 0b1111_1111 = "A | B | C | 0xf0" 0b0000_1000 = "0x8"
Strict mode will unset any unknown bits, as well as bits not contained in any defined named flags:
0b1000_0000 = "" 0b1111_1111 = "A | B | C" 0b0000_1000 = ""