Crate petra

Source
Expand description

petra is a simple binary encoding library with support for flexible containers.

Heavily inspired by MessagePack, petra aims to provide more or less the same features with an additional goal of supporting flexible maps and arrays. There are both advantages and disadvantages associated with such a feature, therefore petra might not be the right tool for many jobs, but it is a useful tool to have around nevertheless.

In a similar fashion to MessagePack, petra uses 8-bit Markers to delimit and discriminate data. Markers are defined for a variety of data types and representations. Each piece of data is preceeded by a marker identifying the type and lenght of the data. For more information on the encoding format, please see the specifications.

§Buffers

Two buffer variants are provided by the library: ReadBuffer and WriteBuffer. These buffers are at the core of the entire encoding and decoding mechanics of the library. They wrap around references to data and provide reading and writing capabilities with cursor tracking and a few more features.

§Encoding and decoding

The decode and encode modules provide low-level functions for reading and writing directly to and from ReadBuffer and WriteBuffer instances. The higer-level de and ser modules provide standard Serializer and Deserializer implementations for working for arbitrary data types.

§Examples

§Serialization from a struct and manual data decoding

use serde::Serialize;

use petra::decode::*;
use petra::{Marker, ReadBuffer, WriteBuffer};
use petra::ser::Serializer;

#[derive(Serialize)]
struct Foo {
    x: u8,
    y: String,
}

let mut data = [0u8; 1024];
let mut buffer = WriteBuffer::from(&mut data);

let mut ser = Serializer::from_buffer(&mut buffer);
let foo = Foo { x: 42, y: "it works".into() };

foo.serialize(&mut ser);

let mut buffer = buffer.into_read_buffer();

// The struct `foo` is encoded as a map with two elements.
assert_eq!(read_map(&mut buffer), Ok(Some(2)));

// The keys in the map are the field names.
// The values are u8 and str.

// The first field.
assert_eq!(read_str(&mut buffer), Ok("x"));
assert_eq!(read_unsigned(&mut buffer), Ok(42));

// The second field.
assert_eq!(read_str(&mut buffer), Ok("y"));
assert_eq!(read_str(&mut buffer), Ok("it works"));

§Manual data encoding and deserialization into a struct

use serde::Deserialize;

use petra::encode::*;
use petra::{Marker, ReadBuffer, WriteBuffer};
use petra::de::Deserializer;

#[derive(Debug, Deserialize, PartialEq)]
struct Foo<'a> {
    a: u16,

    #[serde(borrow)]
    b: Vec<&'a str>,

    c: bool,
}

let mut data = [0u8; 1024];
let mut buffer = WriteBuffer::from(&mut data);

// The struct `foo` is encoded as a map with three elements.
assert!(matches!(write_map(&mut buffer, Some(3)), Ok(Marker::ImmMap { len: 3 })));

// The keys in the map are the field names.
// The values are of types u16, flexible array of String, and bool.

// The first field.
assert!(matches!(write_str(&mut buffer, "a"), Ok(Marker::ImmStr { len: 1 })));
assert!(matches!(write_unsigned(&mut buffer, 1024), Ok(Marker::U16)));

// The second field.
assert!(matches!(write_str(&mut buffer, "b"), Ok(Marker::ImmStr { len: 1 })));
assert!(matches!(write_array(&mut buffer, None), Ok(Marker::AFlex)));

// Now we may encode any number of array elements of type String, let's say 2 elements.
{
    assert!(matches!(write_str(&mut buffer, "first"), Ok(Marker::ImmStr { len: 5 })));
    assert!(matches!(write_str(&mut buffer, "second"), Ok(Marker::ImmStr { len: 6 })));
}

// And we terminate the flexible array.
assert!(matches!(write_terminator(&mut buffer), Ok(Marker::Term)));

// The last field.
assert!(matches!(write_str(&mut buffer, "c"), Ok(Marker::ImmStr { len: 1 })));
assert!(matches!(write_bool(&mut buffer, true), Ok(Marker::Bool { value: true })));

let mut buffer = buffer.into_read_buffer();
let mut de = Deserializer::from_buffer(&mut buffer);

assert_eq!(
    Foo::deserialize(&mut de),
    Ok(Foo {
        a: 1024,
        b: vec!["first", "second"],
        c: true,
    }),
);

Modules§

deserde
Arbitrary data deserialization.
decode
Low-level primitives for data decoding.
encode
Low-level primitives for data encoding.
serserde
Arbitrary data serialization.

Structs§

ReadBuffer
A read buffer with cursor, peaking, borrowing and last read undo.
Snapshot
A snapshot of the cursor position within a buffer.
WriteBuffer
A write buffer with cursor, last write undo and error flag.

Enums§

Error
An error which may occur during encoding or decoding.
Marker
Data marker for the encoded data.