Rust 的位级封装和解封
Packing and unpacking bit-level structures is usually a programming tasks that needlessly reinvents the wheel. This library provides a meta-programming approach, using attributes to define fields and how they should be packed. The resulting trait implementations provide safe packing, unpacking and runtime debugging formatters with per-field documentation generated for each structure.
std: use the Rust standard library. Default.alloc: use the alloc crate for no_std + alloc scenarios. Requires nightly Rust.use_serde: add serialization support to the built-in helper types.byte_types_64, byte_types_256: enlarge the size of the generated array, byte and bit width types.[dependencies]
packed_struct = "0.10"
// This is only needed for pre Rust 2018
#[macro_use] extern crate packed_struct;
// Prelude import with the common imports
use packed_struct::prelude::*;
…
use packed_struct::prelude::*;
#[derive(PackedStruct)]
#[packed_struct(attr1="val", attr2="val")]
pub struct Structure {
#[packed_field(attr1="val", attr2="val")]
field: u8
}
| Attribute | Values | Comment |
|---|---|---|
size_bytes |
1 ... n |
Size of the packed byte stream |
bit_numbering |
msb0 or lsb0 |
Bit numbering for bit positioning of fields. Required if the bits attribute field is used. |
endian |
msb or lsb |
Default integer endianness |
| Attribute | Values | Comment |
|---|---|---|
bits |
0, 0..1, ... |
Position of the field in the packed structure. Three modes are supported: a single bit, the starting bit, or a range of bits. See details below. |
bytes |
0, 0..1, ... |
Same as above, multiplied by 8. |
size_bits |
1, ... |
Specifies the size of the packed structure. Mandatory for certain types. Specifying a range of bits like bits="0..2" can substite the required usage of size_bits. |
size_bytes |
1, ... |
Same as above, multiplied by 8. |
element_size_bits |
1, ... |
For packed arrays, specifies the size of a single element of the array. Explicitly stating the size of the entire array can substite the usage of this attribute. |
element_size_bytes |
1, ... |
Same as above, multiplied by 8. |
ty |
enum |
Packing helper for primitive enums. |
endian |
msb or lsb |
Integer endianness. Applies to u16/i16 and larger types. |
Used for either bits or bytes on fields. The examples are for MSB0 positioning.
| Value | Comment |
|---|---|
0 |
A single bit or byte |
0.., 0: |
The field starts at bit zero |
0..2 |
Exclusive range, bits zero and one |
0:1, 0..=1 |
Inclusive range, bits zero and one |
use packed_struct::prelude::*;
#[derive(PackedStruct)]
pub struct EndianExample {
#[packed_field(endian="lsb")]
int1: u16,
#[packed_field(endian="msb")]
int2: i32
}
fn main() -> Result {
let example = EndianExample {
int1: 0xBBAA,
int2: 0x11223344
};
let packed = example.pack()?;
assert_eq!([0xAA, 0xBB, 0x11, 0x22, 0x33, 0x44], packed);
Ok(())
}
use packed_struct::prelude::*;
#[derive(PackedStruct)]
#[packed_struct(endian="lsb")]
pub struct LsbIntExample {
int1: Integer>,
}
fn main() -> Result {
let example = LsbIntExample {
int1: 0xCCBBAA.into()
};
let packed = example.pack()?;
assert_eq!([0xAA, 0xBB, 0xCC], packed);
Ok(())
}
…
…
Supported backing integer types: u8, u16, u32, u64, i8, i16, i32, i64.
Explicit or implicit backing type:
use packed_struct::prelude::*;
#[derive(PrimitiveEnum, Clone, Copy, PartialEq, Debug)]
pub enum ImplicitType {
VariantMin = 0,
VariantMax = 255
}
#[derive(PrimitiveEnum_i16, Clone, Copy)]
pub enum ExplicitType {
VariantMin = -32768,
VariantMax = 32767
}
fn main() {
use packed_struct::PrimitiveEnum;
let t = ImplicitType::VariantMin;
let tn: u8 = t.to_primitive();
assert_eq!(0, tn);
let t = ImplicitType::from_primitive(255).unwrap();
assert_eq!(ImplicitType::VariantMax, t);
}
use packed_struct::prelude::*;
#[derive(PrimitiveEnum_u8, Debug, Clone, Copy)]
pub enum Field {
A = 1,
B = 2,
C = 3
}
#[derive(PackedStruct, Debug, PartialEq)]
#[packed_struct(bit_numbering="msb0")]
pub struct Register {
#[packed_field(bits="0..4", ty="enum")]
field: EnumCatchAll
}
License: MIT OR Apache-2.0
暂无开放 Issues,或尚未同步最近议题。