[][src]Module packs::packable

Overview

The main API traits are Pack and Unpack. Both are high-level traits for types which can be encoded and decoded following the PackStream specification. This includes the basic types as well as compound structures.

Encoding and Decoding Strategy

The encode function for all basic types tries to be as space efficient as the specification allows. E.g. an 0: i32 will get encoded just with 0x00 instead of some full Int32. The decode function though reads any correct encoded value into its target type. This means, that decode : Bytes -> Value is not injective; different byte sequences can be decoded into the same value:

use packs::packable::{Pack, Unpack};
let mut bytes_i16 : &[u8] = &[0xC9, 0xFF, 0xFF]; // -1 as Int16
let mut bytes_i8 : &[u8] = &[0xC8, 0xFF]; // -1 as Int8

let decoded_i16 = i64::decode(&mut bytes_i16).unwrap();
let decoded_i8 = i64::decode(&mut bytes_i8).unwrap();

assert_eq!(decoded_i8, decoded_i16);

This especially means that encode and decode do not need to be inverses:

use packs::packable::{Pack, Unpack};
let mut bytes : &[u8] = &[0xC9, 0x00, 0x01]; // 1 as Int16
let decoded = i64::decode(&mut bytes).unwrap();

// but will be encoded just as `TINY_PLUS_INT` here: `0x01`.
let mut encoded_bytes = Vec::new();
decoded.encode(&mut encoded_bytes).unwrap();

assert_eq!(encoded_bytes.as_slice(), &[0x01]);

If the base value can only be encoded in a unique manner, then encode and decode are inverses:

use packs::packable::{Pack, Unpack};
let mut buffer = Vec::new();
let value: i64 = 42334388282948;

value.encode(&mut buffer).unwrap();
let res = i64::decode(&mut buffer.as_slice()).unwrap();

assert_eq!(value, res);

as well as in the other direction:

use packs::packable::{Pack, Unpack};
use std::io::Cursor;
let buffer: &[u8] = &[0xC9, 0x7F, 0x0C];
let mut cursor = Cursor::new(buffer);
let res = i64::decode(&mut cursor).unwrap();
let mut res_buffer = Vec::new();
res.encode(&mut res_buffer).unwrap();

cursor.set_position(0);
assert_eq!(cursor.into_inner(), res_buffer.as_slice());

Implementation for user-defined types

An implementation for new base types is not foreseen. Base types are built into the library itself and should be rather (pull) requested.

An implementation for complex types (i.e. structures) on the other hand, is possible and intended. Structures are packed with an extra tag byte to denote which structure is packed.

Traits

Pack

Trait to encode values into any writer using PackStream; using a space efficient way to pack.

Unpack

Trait to decode values from a stream using PackStream.