packed_bits
Zero-cost, const-friendly, no_std and memory efficient bit packing library
Installation
Add packed_bits to your Cargo.toml:
[]
= "0.3"
The crate is no_std by default; enable features as needed:
[]
# std (Error impl for FieldError)
= { = "0.3", = ["std"] }
# typed fields via #[derive(PackedField)]
= { = "0.3", = ["derive"] }
To use the derive macro directly, add it too:
[]
= { = "0.3", = ["derive"] }
= "0.3"
Usage
use packed_bits;
// LC-3 ADD instruction (16-bit). Fields map directly to the ISA layout:
// ADD DR, SR1, SR2 -> 0001 DR SR1 0 000 SR2 00
// ADD DR, SR1, imm5 -> 0001 DR SR1 1 imm5
packed_bits!;
// ADD R2, R1, R3 (register mode) -> 0x144C
let add_reg = from;
assert_eq!;
// ADD R0, R1, #5 (immediate mode) -> 0x1065
let add_imm = new;
assert_eq!;
More Examples
Packing domain values
packed_bits!;
let birthday = new;
// read values
println!; // 25
println!; // 12
println!; // 99
// update values (chainable, returns &mut Self)
birthday.set_day.set_month.set_year;
assert_eq!;
// const-compatible creation
const EPOCH: Date = new;
// raw bit access
let mut epoch = EPOCH;
epoch.set_bit.toggle_bit;
assert_eq!;
assert_eq!;
epoch.clear_bit;
assert_eq!;
// raw storage access
assert_eq!;
// bit width
assert_eq!;
// Memory usage
assert_eq!; // 2 bytes!
Typed fields with derive
use packed_bits;
packed_bits!;
let pixel = new;
assert_eq!;
assert_eq!;
assert_eq!;
// construction from raw bits fails if any field has no valid value
assert!;
Features
- Minimal dependencies - Pure Rust implementation
- no_std compatible - Works in embedded environments
- Zero-cost abstractions - Compiles to raw bit operations
- Type safe - Each field gets its own accessor and setter method
- Memory efficient - Pack multiple values into single integers
- Compile-time validation - Catches bit overflow at build time
- const fn support - Create packed values at compile time via
Date::new() - Chainable setters - Update fields fluently via
set_<field>() - Runtime overflow detection - Panics when a value exceeds its field capacity
- Raw bit manipulation -
get_bit,set_bit,clear_bit,toggle_bit - Raw storage access -
get_raw,set_raw,from_raw - Conversion support -
From<Raw>/TryFrom<Raw>construction for typed and bare fields
Important Notes
- Make sure your bit counts add up to fit in your storage type
- u16 can hold 16 bits total, u32 can hold 32 bits, etc.
- Each field gets a method with the same name to read its value, plus
set_<field>to update it - Values are stored from lowest bits to highest bits in declaration order
- Maximum value for each field is (2^bits) - 1
- Passing an out-of-range value to
new/setters panics instead of silently truncating - Bare-field structs get
From<Raw>(infallible); typed-field structs getTryFrom<Raw>, which fails if any field's raw bits have no valid value (e.g. an enum discriminant hole) - Bit manipulation methods operate on the raw underlying storage, not logical fields
- Bit indices are 0-based; out-of-range indices panic
TODO
- Implement
Display/FromStrconversions - Implement support for
boolfields - Implement support for signed integer fields