Expand description
Watto
Utilities for parsing and serializing Plain Old Data.
Pod
The API is primarily defined on the Pod
trait, which can be implemented
for #[repr(C)]
types. It is then possible to get a reference to that Pod
or a slice thereof directly from an underlying buffer.
Similarly, the Pod
can also be turned into its underlying buffer as well,
for example to write it out into an output buffer.
Features
writer
: Exports an additional Writer
wrapping a std::io::Write
which allows explicitly aligning the output buffer by adding padding bytes.
strings
: Exports a StringTable
for serializing and reading deduplicated strings.
End-to-End Example
use std::mem;
use std::io::Write;
use watto::Pod;
/// Our format looks like this:
/// * A header, containing the number of `A`s.
/// * An aligned slice of `A`s (length given by the header)
/// * An aligned slice of `B`s (length implicitly given by end of buffer)
#[repr(C)]
struct Header {
version: u32,
num_as: u32,
}
unsafe impl Pod for Header {}
#[repr(C)]
#[derive(Debug, PartialEq)]
struct A(u16);
unsafe impl Pod for A {}
#[repr(C)]
#[derive(Debug, PartialEq)]
struct B(u64);
unsafe impl Pod for B {}
// Writing into an output buffer:
let mut writer = watto::Writer::new(vec![]);
writer.write_all(Header { version: 1, num_as: 3 }.as_bytes()).unwrap();
writer.align_to(mem::align_of::<A>()).unwrap();
writer.write_all(&[A(1), A(2), A(3)].as_bytes()).unwrap();
writer.align_to(mem::align_of::<B>()).unwrap();
writer.write_all(&[B(4), B(5), B(6)].as_bytes()).unwrap();
let buffer = writer.into_inner();
// Reading from a buffer:
let buffer = &buffer;
let (header, buffer) = Header::ref_from_prefix(buffer).unwrap();
let (_, buffer) = watto::align_to(buffer, mem::align_of::<A>()).unwrap();
let (r#as, buffer) = A::slice_from_prefix(buffer, header.num_as as usize).unwrap();
let (_, buffer) = watto::align_to(buffer, mem::align_of::<B>()).unwrap();
let bs = B::slice_from_bytes(buffer).unwrap();
assert_eq!(header.num_as, 3);
assert_eq!(r#as, &[A(1), A(2), A(3)]);
assert_eq!(bs, &[B(4), B(5), B(6)]);
Alternatives
Watto is strongly inspired by zerocopy
.
Differences between the two include:
zerocopy
has two distinct traits for reading and writing bytes,watto
only has one for both.- In
zerocopy
, reading a value requires wrapping it inLayoutVerified
. Inwatto
, types implementingPod
can be read directly. watto
includes aWriter
that allows explicit alignment of output.watto
includes aStringTable
for (de)serializing strings.zerocopy
includes endianness-aware integer types.
Why Watto?
Qui-Gon Jinn: I have… acquired a pod in a game of chance. The fastest ever built.
Watto: I hope you didn’t kill anyone I know for it.
License
Watto is licensed under the Apache-2.0 license.
Structs
strings
A struct for storing strings without duplicates.
Enums
strings
An error when trying to read a string from a serialized StringTable
.
Traits
Plain Old Data
Functions
Splits the given bytes
into padding and a slice that is properly aligned
to align
bytes.