Expand description
§packed_bits
Memory-efficient bit packing library. Define a packed_bits struct that
stores multiple fields in a single integer, using only as many bits as each
field needs.
§Usage
use packed_bits::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!(
Lc3Add: u16 {
value: 5, // SR2 (register mode) or imm5 (immediate mode)
imm: 1, // 0 = register mode, 1 = immediate mode
sr1: 3,
dr: 3,
opcode: 4, // 0b0001 for ADD
}
);
// ADD R2, R1, R3 (register mode) -> 0x144C
let add_reg = Lc3Add::from(0x144C);
assert_eq!((0b01100, 0, 1, 2, 0b0001),
(add_reg.value(), add_reg.imm(), add_reg.sr1(), add_reg.dr(), add_reg.opcode()));
// ADD R0, R1, #5 (immediate mode) -> 0x1065
let add_imm = Lc3Add::new(0b00101, 1, 1, 0, 0b0001);
assert_eq!(0x1065, add_imm.get_raw());
// read a single field
assert_eq!(0b00101, add_imm.value());
// update a field (chainable, returns &mut Self)
let mut add = add_imm;
add.set_dr(1).set_sr1(2);
assert_eq!(1, add.dr());
// raw bit access
let mut flags = add;
flags.set_bit(5, true).toggle_bit(9);
assert!(flags.get_bit(5));
flags.clear_bit(5);
assert!(!flags.get_bit(5));
// const-compatible creation
const ADD_R0_R1_5: Lc3Add = Lc3Add::new(0b00101, 1, 1, 0, 0b0001);
assert_eq!(0x1065, ADD_R0_R1_5.get_raw());§Typed fields
Fields can also have a type, backed by the PackedField trait. Fieldless
enums get an implementation via the derive feature:
use packed_bits::{packed_bits, PackedField};
#[derive(PackedField, Debug, Clone, Copy, PartialEq, Eq)]
enum Color {
Red = 0,
Green = 1,
Blue = 2,
}
packed_bits!(
Pixel: u16 {
color: Color = 2,
alpha: u8 = 8,
}
);
pub fn run() {
let pixel = Pixel::new(Color::Blue, 200);
assert_eq!(Some(Color::Blue), pixel.color());
assert_eq!(2, pixel.color_raw());
assert_eq!(Some(200), pixel.alpha());
// construction from raw bits fails if any field has no valid value
assert!(Pixel::try_from(3).is_err());
}§no_std
packed_bits is no_std by default — no features are required. Opt into
std (for an Error impl on FieldError) or derive (for the
PackedField derive macro) as needed:
packed_bits = { version = "0.3", features = ["derive"] }§Example: memory savings
Eight boolean flags fit in a single byte instead of eight:
Without packing: fin + syn + ack + … (1 byte each) = 8 bytes
With packing: everything fits in just 1 byte!
§Macro parameters
name: The name of the generated structstorage: The underlying data type/size (u8,u16,u32,u64)field: Field name (will also be used as a getter method)bits: Number of bits allocated for this field
§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
- Passing an out-of-range value to
new/setters panics; useset_bit/get_bitfor raw bit access
Re-exports§
pub use static_assertions;
Macros§
- packed_
bits - Defines a packed struct that stores multiple fields in a single integer.
- paste
Structs§
- Field
Error - Error returned when a value exceeds the capacity of a packed field.
Traits§
- Packed
Field - A type that can be packed into a bit field.