scale-encode
parity-scale-codec
provides an Encode
trait which allows types to SCALE encode themselves based on their shape.
This crate builds on this, and allows types to encode themselves based on scale_info
type information. It
exposes two traits:
- An
EncodeAsType
trait which when implemented on some type, describes how it can be SCALE encoded with the help of a type ID and type registry describing the expected shape of the encoded bytes. - An
EncodeAsFields
trait which when implemented on some type, describes how it can be SCALE encoded with the help of a slice ofPortableField
's orPortableFieldId
's and type registry describing the expected shape of the encoded bytes. This is generally only implemented for tuples and structs, since we need a set of fields to map to the provided slices.
Implementations for many built-in types are also provided for each trait, and the macro@EncodeAsType
macro makes it easy to generate implementations for new structs and enums.
Motivation
By de-coupling the shape of a type from how it's encoded, we make it much more likely that encoding some type will succeed, and are no longer reliant on types having a precise layout in order to encode correctly. Some examples of this follow.
use Encode;
use EncodeAsType;
use ;
// We are comonly provided type information, but for our examples we construct type info from
// any type that implements `TypeInfo`.
// Encode the left value via EncodeAsType into the shape of the right value.
// Encode the right value statically.
// Assert that both outputs are identical.
// Start simple; a u8 can EncodeAsType into a u64 and vice versa. Numbers will all
// try to convert into the desired output size, failing if this isn't possible:
assert_encodes_to;
assert_encodes_to;
// Compact encoding is also handled "under the hood" by EncodeAsType, so no "compact"
// annotations are needed on values.
assert_encodes_to;
// Enum variants are lined up by variant name, so no explicit "index" annotation are
// needed either; EncodeAsType will take care of it.
assert_encodes_to;
// EncodeAstype will just ignore named fields that aren't needed:
assert_encodes_to;
// EncodeAsType will attempt to remove any newtype wrappers and such on either
// side, so that they can be omitted without any issue.
assert_encodes_to;
assert_encodes_to;
// Things like arrays and sequences are generally interchangeable despite the
// encoding format being slightly different:
assert_encodes_to;
assert_encodes_to;
// BTreeMap, as a slightly special case, can encode to the same shape as either
// a sequence or a struct, depending on what's asked for:
use BTreeMap;
assert_encodes_to;
assert_encodes_to;