#canon #serialisation #ffi #database #no_std

nightly no-std canonical

A serialization library built for no_std environments where you want to deal with recursive datastructures

8 releases (4 breaking)

0.4.2 Nov 12, 2020
0.4.1 Nov 6, 2020
0.4.0 Oct 21, 2020
0.3.0 Oct 20, 2020
0.0.0 Sep 24, 2020

#124 in Database interfaces

Download history 12/week @ 2020-09-20 3/week @ 2020-09-27 26/week @ 2020-10-04 34/week @ 2020-10-11 97/week @ 2020-10-18 134/week @ 2020-10-25 240/week @ 2020-11-01 112/week @ 2020-11-08 107/week @ 2020-11-15 46/week @ 2020-11-22

202 downloads per month
Used in 11 crates (10 directly)

MPL-2.0 license



Canonical is a serialization library built for no_std environments where you want to deal with recursive datastructures, such as trees.

Its main component is the Canon trait, which specifies that a type can be written into bytes, and also that the length of the written value is known beforehand.

This greatly simplifies dealing with environments lacking allocations, and provides a convenient way to pass values across FFI-barriers.


In order not to have to write all this byte-counting code by hand, canonical includes a derive-macro to implement them for you.

#[derive(Canon, PartialEq, Debug)]
struct A2 {
    a: u8,
    b: u8,

For a more involved example, this is a stack structure from the tests.

enum Stack<T, S>
    S: Store,
    Node { value: T, prev: Repr<Self, S> },

The Repr type here acts as a Box, but is supported in non-allocating code, the trick being that the allocation happens outside, in a special Store abstraction.

pub trait Store {
    type Ident: Ident;
    type Error: From<CanonError>;

    fn put<T: Canon>(t: &mut T) -> Result<Self::Ident, Self::Error>;
    fn get<T: Canon>(id: &Self::Ident) -> Result<T, Self::Error>;

The Ident is a value used to refer to encoded values, this is generally a hash of some sort of the encoded bytes.

In a wasm no_std environment, the put and get of Store can be implemented as a host call, and effectively do the allocations "host-side".