macro_rules! bytestruct {
(
$(#[$meta:meta])*
$vis:vis struct $name:ident ([$unit:tt; $N:tt]) {
$(
$field_vis:vis $field_name:ident: $field_type:tt = $bits:tt
),* $(,)?
}
) => { ... };
(
$(#[$meta:meta])*
$vis:vis struct $name:ident ([$unit:tt; $N:tt]) {
$field_vis:vis $field_name:ident : ($field_type:ty) = @unroll($count:tt)
}
) => { ... };
(
$(#[$meta:meta])*
$vis:vis struct $name:ident ([$unit:tt; $N:tt]) {
$field_vis:vis $field_name:ident : ($field_type:ty) = @unroll_signed($count:tt)
}
) => { ... };
(
$(#[$meta:meta])*
$vis:vis struct $name:ident ($N:tt) {
$(
$field_vis:vis $field_name:ident: $field_type:tt = $bits:tt
),* $(,)?
}
) => { ... };
(@impl_conversions $name:ident, 1) => { ... };
(@impl_conversions $name:ident, 2) => { ... };
(@impl_conversions $name:ident, 3) => { ... };
(@impl_conversions $name:ident, 4) => { ... };
(@impl_conversions $name:ident, 5) => { ... };
(@impl_conversions $name:ident, 6) => { ... };
(@impl_conversions $name:ident, 7) => { ... };
(@impl_conversions $name:ident, 8) => { ... };
(@impl_conversions $name:ident, 16) => { ... };
(@impl_conversions $name:ident, $N:expr) => { ... };
(@impl_wide_conv $name:ident, $N:tt, $prim:ty, $to_name:ident, $from_name:ident, $($idx:literal)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, ) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident bool $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u8 $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u16 $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u32 $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u64 $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u128 $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i8 $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i16 $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i32 $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i64 $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i128 $bits:tt $($rest:tt)*) => { ... };
(@impl_int $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident $field_type:tt $bits:tt $($rest:tt)*) => { ... };
(@impl_signed_int $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident $field_type:tt $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_conversions $name:ident, $unit:tt, $N:tt) => { ... };
(@route_conversions $name:ident, $unit:tt, 1) => { ... };
(@route_conversions $name:ident, $unit:tt, 2) => { ... };
(@route_conversions $name:ident, $unit:tt, 3) => { ... };
(@route_conversions $name:ident, $unit:tt, 4) => { ... };
(@route_conversions $name:ident, $unit:tt, 5) => { ... };
(@route_conversions $name:ident, $unit:tt, 6) => { ... };
(@route_conversions $name:ident, $unit:tt, 7) => { ... };
(@route_conversions $name:ident, $unit:tt, 8) => { ... };
(@route_conversions $name:ident, $unit:tt, 9) => { ... };
(@route_conversions $name:ident, $unit:tt, 10) => { ... };
(@route_conversions $name:ident, $unit:tt, 11) => { ... };
(@route_conversions $name:ident, $unit:tt, 12) => { ... };
(@route_conversions $name:ident, $unit:tt, 13) => { ... };
(@route_conversions $name:ident, $unit:tt, 14) => { ... };
(@route_conversions $name:ident, $unit:tt, 15) => { ... };
(@route_conversions $name:ident, $unit:tt, 16) => { ... };
(@route_conversions $name:ident, $unit:tt, $any:expr) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 1) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 2) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 3) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 4) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 5) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 6) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 7) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 8) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 9) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 10) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 11) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 12) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 13) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 14) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 15) => { ... };
(@impl_typed_uX_methods $name:ident, u8, 16) => { ... };
(@impl_typed_uX_methods $name:ident, u16, 1) => { ... };
(@impl_typed_uX_methods $name:ident, u16, 2) => { ... };
(@impl_typed_uX_methods $name:ident, u16, 3) => { ... };
(@impl_typed_uX_methods $name:ident, u16, 4) => { ... };
(@impl_typed_uX_methods $name:ident, u16, 5) => { ... };
(@impl_typed_uX_methods $name:ident, u16, 6) => { ... };
(@impl_typed_uX_methods $name:ident, u16, 7) => { ... };
(@impl_typed_uX_methods $name:ident, u16, 8) => { ... };
(@impl_typed_uX_methods $name:ident, u32, 1) => { ... };
(@impl_typed_uX_methods $name:ident, u32, 2) => { ... };
(@impl_typed_uX_methods $name:ident, u32, 3) => { ... };
(@impl_typed_uX_methods $name:ident, u32, 4) => { ... };
(@impl_typed_uX_methods $name:ident, u64, 1) => { ... };
(@impl_typed_uX_methods $name:ident, u64, 2) => { ... };
(@impl_typed_uX_methods $name:ident, u128, 1) => { ... };
(@impl_u8_methods $name:ident) => { ... };
(@impl_u16_methods $name:ident) => { ... };
(@impl_u32_methods $name:ident) => { ... };
(@impl_u64_methods $name:ident) => { ... };
(@impl_u128_methods $name:ident) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident ($field_type:ty) = @unroll($count:tt) $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident ($field_type:ty) = @unroll_signed($count:tt) $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, ) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident bool $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u8 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u16 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u32 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u64 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident u128 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i8 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i16 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i32 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i64 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident i128 $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_int $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident $field_type:tt $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_signed_int $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident $field_type:tt $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident ($field_type:ty) $bits:tt $($rest:tt)*) => { ... };
(@impl_typed_fields $name:ident, $unit:tt, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident $field_type:tt $bits:tt $($rest:tt)*) => { ... };
(@read_typed_prim $arr:expr, $unit:tt, $prim:ty, $shift:expr, $bits:tt) => { ... };
(@write_typed_prim $arr:expr, $unit:tt, $prim:ty, $shift:expr, $bits:tt, $val:expr) => { ... };
(@unroll_typed_read $arr:expr, $unit:tt, $prim:ty, $idx:expr, 1, $offset:expr, $bits:expr) => { ... };
(@unroll_typed_read $arr:expr, $unit:tt, $prim:ty, $idx:expr, 2, $offset:expr, $bits:expr) => { ... };
(@unroll_typed_read $arr:expr, $unit:tt, $prim:ty, $idx:expr, 3, $offset:expr, $bits:expr) => { ... };
(@unroll_typed_read $arr:expr, $unit:tt, $prim:ty, $idx:expr, 4, $offset:expr, $bits:expr) => { ... };
(@unroll_typed_read $arr:expr, $unit:tt, $prim:ty, $idx:expr, 5, $offset:expr, $bits:expr) => { ... };
(@unroll_typed_read $arr:expr, $unit:tt, $prim:ty, $idx:expr, 6, $offset:expr, $bits:expr) => { ... };
(@unroll_typed_read $arr:expr, $unit:tt, $prim:ty, $idx:expr, 7, $offset:expr, $bits:expr) => { ... };
(@unroll_typed_read $arr:expr, $unit:tt, $prim:ty, $idx:expr, 8, $offset:expr, $bits:expr) => { ... };
(@unroll_typed_read $arr:expr, $unit:tt, $prim:ty, $idx:expr, $any:expr, $offset:expr, $bits:expr) => { ... };
(@unroll_typed_write $arr:expr, $unit:tt, $prim:ty, $idx:expr, $count:tt, $offset:expr, $bits:expr, $val:expr) => { ... };
(@unroll_typed_write_fresh $arr:expr, $unit:tt, $prim:ty, $idx:expr, $count:tt, $offset:expr, $bits:expr, $val:expr) => { ... };
(@unroll_typed_write_raw $arr:expr, $unit:tt, $prim:ty, $idx:expr, 1, $full:expr) => { ... };
(@unroll_typed_write_raw $arr:expr, $unit:tt, $prim:ty, $idx:expr, 2, $full:expr) => { ... };
(@unroll_typed_write_raw $arr:expr, $unit:tt, $prim:ty, $idx:expr, 3, $full:expr) => { ... };
(@unroll_typed_write_raw $arr:expr, $unit:tt, $prim:ty, $idx:expr, 4, $full:expr) => { ... };
(@unroll_typed_write_raw $arr:expr, $unit:tt, $prim:ty, $idx:expr, 5, $full:expr) => { ... };
(@unroll_typed_write_raw $arr:expr, $unit:tt, $prim:ty, $idx:expr, 6, $full:expr) => { ... };
(@unroll_typed_write_raw $arr:expr, $unit:tt, $prim:ty, $idx:expr, 7, $full:expr) => { ... };
(@unroll_typed_write_raw $arr:expr, $unit:tt, $prim:ty, $idx:expr, 8, $full:expr) => { ... };
(@unroll_typed_write_raw $arr:expr, $unit:tt, $prim:ty, $idx:expr, $any:expr, $full:expr) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident ($field_type:ty) $bits:tt $($rest:tt)*) => { ... };
(@impl_fields $name:ident, $prim:ty, $shift:expr, $field_vis:vis $field_name:ident $field_type:tt $bits:tt $($rest:tt)*) => { ... };
(@read_localized_prim $arr:expr, $shift:expr, $bits:tt) => { ... };
(@write_localized_prim $arr:expr, $shift:expr, $bits:tt, $val:expr) => { ... };
}Expand description
A unique declarative macro for generating bitfields backed by fixed-size byte arrays.
Unlike standard bitfield libraries that restrict storage to primitives (u8-u128),
bytestruct allows array-backed storage ([u8; 1-16]) while maintaining
register-wide optimization through “Acting Primitives”.
This macro generates a struct wrapping [u8; N]. It uses an internal “acting primitive”
(u32, u64, or u128) based on $N$ to perform efficient bitwise operations.
§Examples
§Cross-Boundary Packing in a Byte Array
use bitcraft::bytestruct;
bytestruct! {
// Packs fields into a 5-byte (40-bit) storage array.
pub struct NetworkPacket([u8; 5]) {
pub version: u8 = 4, // Bits 0-3
pub is_encrypted: bool = 1, // Bit 4
pub payload_id: u32 = 24, // Bits 5-28 (crosses 3 byte boundaries!)
pub checksum: u16 = 11, // Bits 29-39 (crosses 2 byte boundaries!)
}
}
let mut packet = NetworkPacket::default()
.with_version(4)
.with_is_encrypted(true)
.with_payload_id(0xABCDEF);
assert_eq!(packet.version(), 4);
assert!(packet.is_encrypted());
assert_eq!(packet.payload_id(), 0xABCDEF);
// The raw array perfectly packs these bits densely
let raw: [u8; 5] = packet.to_array();§Advanced Typed Storage ([u16; N], [u32; N]) & Signed Fields
bytestruct! natively supports generic integer array types, which enables creating large dense
multi-element bitfields with highly efficient memory bounds.
use bitcraft::bytestruct;
bytestruct! {
// A 128-bit wrapper stored as four `u32` blocks.
pub struct HugeStorage([u32; 4]) {
pub header: u16 = 16,
pub sensor_val: i32 = 20, // A 20-bit signed field (-524,288 to 524,287)
pub hash: u64 = 64, // 64-bit contiguous field crossing u32 boundaries
// ... other fields filling the 128 bits ...
}
}
let mut mem = HugeStorage::default();
mem.set_sensor_val(-400_000);
assert_eq!(mem.sensor_val(), -400_000);§Implementation Details
bytestruct! uses an advanced “Token-Tree (TT) Muncher” pattern coupled with dynamic
type resolution via the hidden BitenumType trait. It completely unrolls array reads
and writes into single-primitive logic.
For instance, if you define a 5-byte array ([u8; 5]), bytestruct! computes the total
number of bits (40 bits). Through crate::Bits<40>, the Rust type system dynamically resolves
the “Acting Primitive” to u64. All internal field getters and setters will seamlessly
load the required array slice into a u64 register, perform the bitwise logic, and write
the bytes back without branching.