Highly spatially efficient serialization format supporting #[no_std] and making zero allocations.
All sizes listed in bits
| Type | Value | mincodec | CBOR | bincode | MessagePack | Postcard |
|---|---|---|---|---|---|---|
Option<bool> | Some(true) | 2 | 8 | 16 | 8 | 16 |
Option<bool> | Some(false) | 2 | 8 | 16 | 8 | 16 |
Option<bool> | None | 1 | 8 | 8 | 8 | 8 |
String | "hello" | 48 | 48 | 104 | 48 | 48 |
Vec<bool> | [true, false, true] | 11 | 32 | 88 | 32 | 32 |
(bool, u8) | (false, 3) | 9 | 24 | 16 | 24 | 16 |
CustomOption<bool> | Some(true) | 2 | 56 | 40 | 24 | 16 |
() | () | 0 | 8 | 0 | 8 | 0 |
[String; 0] | [] | 0 | 8 | 0 | 8 | 0 |
[bool; 2] | [true, false] | 2 | 24 | 16 | 24 | 16 |
Bit | High | 1 | 40 | 32 | 24 | 8 |
OneVariant | Variant | 0 | 64 | 32 | 24 | 8 |
pubenumCustomOption<T>{Some(T),None,}pubenumBit{High,Low,}pubenumOneVariant{Variant,}- True frameless design (no headers/prefixing/etc. in multi-item streams)
- Perfect incremental deserialization (intermediate buffers are filled per-bit as data becomes available), no cycles are wasted re-deserializing data
#![no_std]support using core-futures-io- Compatibility with both
tokioandasync_stdusing compatibility adapters from core-futures-io - Bit-level serialization using bitbuf facilitates the extreme spatial efficiency displayed above
- Efficient size prefixing for DSTs using bitbuf-vlq
- Asynchronicity permits deserialization of data as it becomes available over transport, spreading the time cost of deserialization or serialization over the transport's bandwidth domain
- Asynchronicity permits dependency of serialized/deserialized types on futures, the dual of transport-side asynchronicity
serde-style derive macro for straightforward implementation with support for generic parametrization
use async_std::net::{TcpStream,TcpListener};use core_futures_io::FuturesCompat;use futures::{executor::block_on,StreamExt};use mincodec::{AsyncWriter,MinCodec,AsyncReader};use std::thread::spawn;#[derive(MinCodec,Debug)]enumPermission{Read,Write,Invite{remaining:u32},}#[derive(MinCodec,Debug)]structCapability{permission:Permission,domain:String,}#[derive(MinCodec,Debug)]structUser{name:String,capabilities:Vec<Capability>,}#[derive(MinCodec,Debug)]enumAction<T>{Create(T),Remove{index:u32},}#[derive(MinCodec,Debug)]structPost{content:String,date:u64,}#[derive(MinCodec,Debug)]structData{user:User,action:Action<Post>,}fnmain(){let thread = spawn(|| block_on(async{let listener = TcpListener::bind("127.0.0.1:8080").await.expect("could not bind listener");letmut incoming = listener.incoming();ifletSome(stream) = incoming.next().await{let stream = stream.expect("listener-side connection error");println!("received: {:?}",AsyncReader::<_,Data>::new(FuturesCompat::new(stream)).await.expect("error reading data and deserializing"));}}));block_on(async{let stream = TcpStream::connect("127.0.0.1:8080").await.expect("could not connect");AsyncWriter::new(FuturesCompat::new(stream),Data{action:Action::Create(Post{content:"Hello there!".to_owned(),date:1230192809,}),user:User{name:"J. Doe".to_owned(),capabilities:vec![Capability{
permission:Permission::Write,
domain:"posts".to_owned(),},Capability{
permission:Permission::Read,
domain:"posts".to_owned(),},],},},).await.expect("could not serialize and transmit");});
thread.join().unwrap();}