33 releases (11 stable)
1.1.7 | Jun 6, 2024 |
---|---|
1.1.6 | Jan 5, 2024 |
0.2.9 | Dec 30, 2023 |
0.1.12 | Nov 26, 2023 |
#827 in Rust patterns
Used in 3 crates
(2 directly)
41KB
929 lines
Binmarshal
Pack and unpack structs and enums into and out of binary data streams.
Add to your project
cargo add binmarshal
Packing Structs and Enums
use binmarshal::*;
#[derive(Debug, Clone, BinMarshal)]
#[marshal(tag_type = u8)]
enum MyEnum {
#[marshal(tag = "0")]
Variant1,
#[marshal(tag = "1")]
Variant2 {
#[marshal(bits = 4)]
a: u8,
#[marshal(align = 1)]
b: u16,
c: LengthTaggedVec<u8, i32>
}
}
fn main() {
let v = MyEnum::Variant2 {
a: 13,
b: 5192,
c: LengthTaggedVec::new(vec![ -12, -242, 12034 ])
};
// Packing
let mut bytes = [0u8; 256];
let mut writer = BufferBitWriter::new(&mut bytes);
v.write(&mut writer, ());
let slice = writer.slice(); // Gives you a &[u8] reference of the appropriate length, as a subset of "bytes"
// Unpacking
let v = MyEnum::read(&mut BitView::new(slice), ()).unwrap();
}
Using Context
Context allows you to pass variables between structs and enums, primarily for tagging enums. If you are using tagged enums with context, you must call .update()
prior to writing.
use binmarshal::*;
#[derive(Clone)]
struct MyContext {
tag: u8
}
#[derive(Debug, Clone, BinMarshal)]
#[marshal(ctx = MyContext, tag_type = u8, tag = "ctx.tag")]
enum MyEnum {
#[marshal(tag = "1")]
Variant1,
#[marshal(tag = "2")]
Variant2,
}
#[derive(Debug, Clone, BinMarshal)]
struct MyStruct {
variant: u8,
#[marshal(ctx = "construct", ctx_member(field = "tag", member = "variant"))]
inner: MyEnum
}
Examples
More complex examples are provided under examples
Dependencies
~0.8–1.6MB
~34K SLoC