[][src]Attribute Macro modular_bitfield::bitfield

#[bitfield]

Applicable to structs to turn their fields into compact bitfields.

Generated API

By default this generates the following API:

  • Constructors:

    1. new(): Initializes all bits to 0 even if 0 bits may be invalid. Note that invalid bit patterns are supported in that getters and setters will be protecting accesses.
  • Getters:

    For every field f we generate the following getters:

    1. f(): Returns the value of f and might panic if the value contains an invalid bit pattern.
    2. f_or_err(): Returns the value of f or an error if the value contains an invalid bit pattern.
  • Setters:

    For every field f we generate the following setters:

    1. set_f(new_value): Sets the value of f to new_value and might panic if new_value is out of bounds for the bit width of f.
    2. set_f_checked(new_value): Sets the value of f to new or returns an error if new_value if out of bounds for the bit width of f.
    3. with_f(new_value): Similar to set_f but consumes and returns Self. Primarily useful for method chaining.
    4. with_f_checked(new_value): Similar to set_f_checked but consumes and returns Self. Primarily useful for method chaining.
  • Conversions:

    • from_bytes(bytes): Allows to constructor the bitfield type from a fixed array of bytes.
    • into_bytes(): Allows to convert the bitfield into its underlying byte representation.

Parameters

The following parameters for the #[bitfield] macro are supported:

Parameter: bytes = N

This ensures at compilation time that the resulting #[bitfield] struct consists of exactly N bytes. Yield a compilation error if this does not hold true.

Example

#[bitfield(bytes = 2)]
pub struct SingedInt {
    sign: bool, //  1 bit
    value: B15, // 15 bits
}

Parameter: filled: bool

If filled is true ensures that the #[bitfield] struct defines all bits and therefore has a bitwidth that is divisible by 8. If filled is false ensures the exact opposite.

The default value is: true

Example

#[bitfield(filled = false)]
pub struct Package {
    is_received: bool, // 1 bit
    is_alive: bool,    // 1 bit
    status: B2,        // 2 bits
}

Parameter: specifier: bool

If specifier is true the #[bitfield] macro will additionally generate an implementation for the Specifier trait. This is limited to bitfield types that have a total bit width of 128 bit or fewer. This is ensured at compile time.

Implementing the Specifier trait allows for the type to be used as a field within another #[bitfield] annotated type.

Example

#[bitfield(specifier = true, filled = false)]
pub struct Header {
    is_received: bool, // 1 bit
    is_alive: bool,    // 1 bit
    status: B2,        // 2 bits
}

Now the above Header bitfield type can be used in yet another #[bitfield] annotated type:

#[bitfield]
pub struct Base {
    header: Header, //  4 bits
    content: B28,   // 28 bits
}

Field Parameter: #[bits = N]

To ensure at compile time that a field of a #[bitfield] struct has a bit width of exactly N a user may add #[bits = N] to the field in question.

Example

#[bitfield]
pub struct Base {
    #[bits = 4]
    header: Header, //  4 bits
    content: B28,   // 28 bits
}

Features

Supports #[repr(uN)]

It is possible to additionally annotate a #[bitfield] annotated struct with #[repr(uN)] where uN is one of u8, u16, u32, u64 or u128 in order to make it conveniently interchangeable with such an unsigned integer value.

As an effect to the user this implements From implementations between the chosen primitive and the bitfield as well as ensuring at compile time that the bit width of the bitfield struct matches the bit width of the primitive.

Example

#[bitfield]
#[repr(u16)]
pub struct SignedU16 {
    sign: bool,     //  1 bit
    abs_value: B15, // 15 bits
}

let sint = SignedU16::from(0b0111_0001);
assert_eq!(sint.sign(), true);
assert_eq!(sint.abs_value(), 0b0011_1000);
assert_eq!(u16::from(sint), 0b0111_0001_u16);

Support: #[derive(Debug)]

If a #[derive(Debug)] is found by the #[bitfield] a naturally formatting implementation is going to be generated that clearly displays all the fields and their values as the user would expect. Also invalid bit patterns for fields are clearly displayed under this implementation.

Example

#[bitfield]
#[derive(Debug)]
pub struct Package {
    is_received: bool, // 1 bit
    is_alive: bool,    // 1 bit
    status: B6,        // 6 bits
}

let package = Package::new()
    .with_is_received(false)
    .with_is_alive(true)
    .with_status(3);
println!("{:?}", package);
assert_eq!(
    format!("{:?}", package),
    "Package { is_received: false, is_alive: true, status: 3 }",
);