#bit-field #struct #macro #debugging #define #strong-typing #heap-allocator

fray

A type-safe and ergonomic Rust library for working with bitfields

3 releases

Uses new Rust 2024

0.1.2 Oct 12, 2025
0.1.1 Oct 2, 2025
0.1.0 Oct 2, 2025

#849 in Rust patterns

Download history 221/week @ 2025-09-29 180/week @ 2025-10-06 88/week @ 2025-10-13 10/week @ 2025-10-20 1/week @ 2025-10-27

299 downloads per month

MIT license

53KB
853 lines

fray

A type-safe and ergonomic Rust library for working with bitfields.

fray lets you define structured bitfields using the #[bitfield] attribute macro, and interact with their fields through strongly-typed getters and setters. This means you can get and set values without manually shifting or masking bits, while still working with packed data in a convenient, high-level way.

Crates.io Documentation CI

Features

  • Define bitfield structs with an attribute macro, using syntax identical to classic Rust structs.
  • Fully compatible with no_std, requiring no heap allocations.
  • Manipulate fields type-safely, without manual shifting or masking.
  • Support both primitive and custom field types.
  • Ensures at compile time that fields fit their containers.
  • Choose different storage backends for bitfields without losing others features.

Documentation

Crate documentation with examples.

Example

use fray::{BitField, FieldType, bitfield};

#[bitfield(repr(u8), derives(Clone, Copy), impls(debug), bitorder(msb0))]
pub struct LinkControl {
    version: Version,
    encrypted: bool,
    ack: bool,
    #[bits(3)]
    sequence: u8,
    #[bits(1)]
    _reserved: (),
}

fn main() {
    let mut link_control = LinkControl::new();
    link_control
        .with::<version>(Version::V3)
        .with::<sequence>(5)
        .with::<ack>(true);

    assert!(link_control.get::<ack>());
    assert_eq!(link_control.try_get::<version>(), Ok(Version::V3));
    assert_eq!(link_control.get::<sequence>(), 5);

    let copy = link_control;

    link_control.set::<ack>(false);
    link_control.set::<encrypted>(true);
    assert!(!link_control.get::<ack>());
    assert!(link_control.get::<encrypted>());

    let copy_fmt = format!("{:?}", copy);
    let expected =
        "LinkControl { version: V3, encrypted: false, ack: true, sequence: 5 }";
    assert_eq!(expected, copy_fmt);
    assert_eq!(copy.into_inner(), 0b11_0_1_101_0);
}

#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Version {
    V0 = 0,
    V1 = 1,
    V2 = 2,
    V3 = 3,
}

impl FieldType for Version {
    const SIZE: usize = 2;
    type BitsType = u8;
}

impl From<Version> for u8 {
    fn from(value: Version) -> Self {
        value as u8
    }
}

impl TryFrom<u8> for Version {
    type Error = u8;

    fn try_from(value: u8) -> Result<Self, Self::Error> {
        Ok(match value {
            0 => Self::V0,
            1 => Self::V1,
            2 => Self::V2,
            3 => Self::V3,
            value => return Err(value),
        })
    }
}

License

This project is licensed under the MIT License.

Dependencies

~0.5–1MB
~22K SLoC