/restruct

Simple parsers for binary data in Rust

Primary LanguageRustMIT LicenseMIT

Build Status Build status Crates.io Version Docs

restruct is used to interpret binary data stored in files or other sources or convert between C structs and Rust types and when using a parser-generator is considered disproportionate. It is a brainchild of Python's struct-module.

The library uses Format Strings as compact descriptions of the binary data and the intended conversion to/from Rust-types. The Format Strings are interpreted at compile-time to generate a type whose functions can be used to convert between unstructured and structured data.

// Generate a parser in little-endian for two 32bit integers, a float and a bool.
#[derive(restruct_derive::Struct)]
#[fmt="<2if?"]
struct FooParser;

// Pack a tuple of two integers, a float and a bool into a [u8; _]-buffer.
let packed = FooParser::pack((1, 2, 3.0, false));
assert_eq!(packed, [1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 64, 64, 0]);
assert_eq!(packed.len(), FooParser::SIZE);

// Packing and unpacking can't fail at runtime.
let unpacked = FooParser::unpack(packed);
assert_eq!(unpacked, (1, 2, 3.0, false));

// Any `io::Read` can be used directly.
let unpacked = FooParser::read_from(&mut &packed[..]).expect("i/o failed");
assert_eq!(unpacked, (1, 2, 3.0, false));

// Any `io::Write` can be used directly.
let mut buffer = Vec::with_capacity(FooParser::SIZE);
FooParser::write_to((1, 2, 3.0, false), &mut buffer).expect("i/o failed");
assert_eq!(&buffer, &packed);
// Because packing and unpacking is const we can use these functions to initialize other consts
const TEAPOT: <Tea as restruct::Struct>::Unpacked = Tea::unpack(*include_bytes!("teapot.bin"));
const TEAPOT_TEMPERATURE: i32 = TEAPOT.0;
const TEAPOT_FILL_STATUS: f32 = TEAPOT.2;
const TEAPOT_ACTIVE: bool = TEAPOT.3;