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:
zerocopyhas two distinct traits for reading and writing bytes,wattoonly has one for both.- In
zerocopy, reading a value requires wrapping it inLayoutVerified. Inwatto, types implementingPodcan be read directly. wattoincludes aWriterthat allows explicit alignment of output.wattoincludes aStringTablefor (de)serializing strings.zerocopyincludes 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
stringsA struct for storing strings without duplicates.
Enums
stringsAn 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.