Skip to main content

Composite Values

We often need to group simple values into more complex ones, without splitting them into several arguments.

Here too we opted for an encoding that is, above all, very easy to read.

Lists of items

This is an umbrella term for all types of lists or arrays of various item types. They all serialize the same way.

Rust types: &[T], Vec<T>, Box<[T]>, LinkedList<T>, VecMapper<T>, etc.

Top-encoding: All nested encodings of the items, concatenated.

Nested encoding: First, the length of the list, encoded on 4 bytes (usize/u32). Then, all nested encodings of the items, concatenated.

Examples

TypeValueTop-level encodingNested encodingExplanation
Vec<u8>vec![1, 2]0x01020x00000002 0102Length = 2
Vec<u16>vec![1, 2]0x000100020x00000002 00010002Length = 2
Vec<u16>vec![]0x0x00000000Length = 0
Vec<u32>vec![7]0x000000070x00000001 00000007Length = 1
Vec< Vec<u32>>vec![ vec![7]]0x00000001 000000070x00000001 00000001 00000007There is 1 element, which is a vector. In both cases the inner Vec needs to be nested-encoded in the larger Vec.
Vec<&[u8]>vec![ &[7u8][..]]0x00000001 070x00000001 00000001 07Same as above, but the inner list is a simple list of bytes.
Vec< BigUint>vec![ 7u32.into()]0x00000001 070x00000001 00000001 07BigUints need to encode their length when nested. The 7 is encoded the same way as a list of bytes of length 1, so the same as above.

Arrays and tuples

The only difference between these types and the lists in the previous section is that their length is known at compile time. Therefore, there is never any need to encode their length.

Rust types: [T; N], Box<[T; N]>, (T1, T2, ... , TN).

Top-encoding: All nested encodings of the items, concatenated.

Nested encoding: All nested encodings of the items, concatenated.

Examples

TypeValueTop-level encodingNested encoding
[u8; 2][1, 2]0x01020x0102
[u16; 2][1, 2]0x000100020x00010002
(u8, u16, u32)[1u8, 2u16, 3u32]0x010002000000030x01000200000003

Options

An Option represents an optional value: every Option is either Some and contains a value, or None, and does not.

Rust types: Option<T>.

Top-encoding: If Some, a 0x01 byte gets encoded, and after it the encoded value. If None, nothing gets encoded.

Nested encoding: If Some, a 0x01 byte gets encoded, and after it the encoded value. If None, a 0x00 byte get encoded.

Examples

TypeValueTop-level encodingNested encodingExplanation
Option<u16>Some(5)0x0100050x010005
Option<u16>Some(0)0x0100000x010000
Option<u16>None0x0x00Note that Some has different encoding than None for any type
Option< BigUint>Some( BigUint::from( 0x1234u32))0x01 00000002 12340x01 00000002 1234The Some value is nested-encoded. For a BigUint this adds the length, which here is 2.