Skip to main content

bitflag

Attribute Macro bitflag 

Source
#[bitflag]
Expand description

§Bitflags

There are times when you just want to define a bitflag, which are just enums that map to bits. Instead of defining a custom type, you can take advantage of the #[bitflag] attribute which generates from_bits and into_bits for enums automatically.

Bitflags only supports unsigned types (u8, u16, u32, u64, u128) and the one of the variants must be annotated with #[base] or #[default] which represents the base value of the bitflag. If #[base] and #[default] are both present, #[base] takes precedence.

use bitfields::bitfield;
use bitfields::bitflag;

/// Annotate an enum with the `#[bitflag]` attribute to automatically generate
/// the `from_bits` and `into_bits` functions for you! One variant must be annotated
/// with `#[base]` which represents the base value of the bitflag.
#[bitflag(u8)]
#[derive(Debug, PartialEq)]
enum RenderMode {
    #[base]
    Normal = 0,
    Mirror = 1,
    Flip = 2,
    // #[default] - Default can be specified but base takes 
    // precedence if both are present.
    Hidden = 3,
}

/// The code that's generated for the `RenderMode` by the
/// `#[bitflag]` attribute saving you the trouble of writing 
/// the `from_bits` and `into_bits` functions yourself.
// impl RenderMode {
//     const fn from_bits(bits: u8) -> Self {
//         match bits {
//             0 => Self::Normal,
//             1 => Self::Mirror,
//             2 => Self::Flip,
//             3 => Self::Hidden,
//             _ => unreachable!(),
//         }
//     }
//
//     const fn into_bits(self) -> u8 {
//         self as u8
//     }
// }

/// Annotate an enum with the `#[bitflag]` attribute to automatically generate
/// the `from_bits` and `into_bits` functions for you! One variant must be annotated
/// with `#[base]` which represents the base value of the bitflag.
#[bitflag(u8)]
#[derive(Debug, PartialEq)]
enum AudioMode {
    #[base]
    Stereo = 0,
    Mono = 1,
    Mute = 2,
    Surround = 3,
}

#[bitfield(u8)]
struct DisplayControl {
    /// Must have the `#[bits]` attribute since the macro has 
    /// no way of knowing how many bits the custom type occupies.
    #[bits(4, default = RenderMode::Normal)]
    render_mode: RenderMode,
    /// Must have the `#[bits]` attribute since the macro has 
    /// no way of knowing how many bits the custom type occupies.
    #[bits(4, default = AudioMode::Stereo)]
    audio_mode: AudioMode,
}

fn main() {
    let display = DisplayControlBuilder::new()
        .with_render_mode(RenderMode::Mirror)
        .with_audio_mode(AudioMode::Mute)
        .build();

    assert_eq!(display.render_mode(), RenderMode::Mirror);
    assert_eq!(display.audio_mode(), AudioMode::Mute);
}
§Bitflag Configuration

Bitflags can be configured with arguments passed to the #[bitflag(...)] attribute (the first argument is always the backing unsigned integer type):

ArgumentValuesDefaultDescription
<backing type>u8, u16, u32, u64, u128RequiredThe storage used by the generated bitflag. Primitive backing types support bitfields up to 128 bits.
from_endianbig, littlebigDefault endianness used by the generated from_bits function.
into_endianbig, littlebigDefault endianness used by the generated into_bits function.
copytrue, falsetrueDetermines whether to derive Copy and Clone automatically for the enum.