#canon #serialisation #no-std #ffi #database

nightly no-std canonical

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

14 releases (5 breaking)

new 0.5.3 Mar 4, 2021
0.5.1 Jan 25, 2021
0.4.4 Dec 29, 2020
0.4.2 Nov 12, 2020

#62 in Database implementations

Download history 103/week @ 2020-11-14 57/week @ 2020-11-21 72/week @ 2020-11-28 46/week @ 2020-12-05 14/week @ 2020-12-12 37/week @ 2020-12-19 28/week @ 2020-12-26 100/week @ 2021-01-02 41/week @ 2021-01-09 80/week @ 2021-01-16 153/week @ 2021-01-23 196/week @ 2021-01-30 191/week @ 2021-02-06 212/week @ 2021-02-13 138/week @ 2021-02-20 90/week @ 2021-02-27

436 downloads per month
Used in 15 crates (14 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".


~10K SLoC