Skip to main content

Custom Types

We sometimes create new types that we want to serialize and deserialize directly when interacting with contracts. For structs and enums it is very easy to set them up, with barely any code.

Custom structures

Any structure defined in a contract of library can become serializable if it is annotated with either or all of: TopEncode, TopDecode, NestedEncode, NestedDecode.

Example implementation:

#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode)]
pub struct Struct {
pub int: u16,
pub seq: Vec<u8>,
pub another_byte: u8,
pub uint_32: u32,
pub uint_64: u64,
}

Top-encoding: All fields nested-encoded one after the other.

Nested encoding: The same, all fields nested-encoded one after the other.

Example value

Struct {
int: 0x42,
seq: vec![0x1, 0x2, 0x3, 0x4, 0x5],
another_byte: 0x6,
uint_32: 0x12345,
uint_64: 0x123456789,
}

It will be encoded (both top-encoding and nested encoding) as: 0x004200000005010203040506000123450000000123456789.

Explanation:

[
/* int */ 0, 0x42,
/* seq length */ 0, 0, 0, 5,
/* seq contents */ 1, 2, 3, 4, 5,
/* another_byte */ 6,
/* uint_32 */ 0x00, 0x01, 0x23, 0x45,
/* uint_64 */ 0x00, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89
]

Custom enums

Any enum defined in a contract of library can become serializable if it is annotated with either or all of: TopEncode, TopDecode, NestedEncode, NestedDecode.

A simple enum example:

Example taken from the multiversx-sc-codec tests.

#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode)]
enum DayOfWeek {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
}

A more complex enum example:

#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode)]
enum EnumWithEverything {
Default,
Today(DayOfWeek),
Write(Vec<u8>, u16),
Struct {
int: u16,
seq: Vec<u8>,
another_byte: u8,
uint_32: u32,
uint_64: u64,
},
}

Nested encoding: First, the discriminant is encoded. The discriminant is the index of the variant, starting with 0. Then the fields in that variant (if any) get nested-encoded one after the other.

Top-encoding: Same as nested-encoding, but with an additional rule: if the discriminant is 0 (first variant) and there are no fields, nothing is encoded.

Example values

The examples below are taken from the multiversx-sc-codec tests.

ValueTop-encoding bytesNested encoding bytes
DayOfWeek::Monday
/* nothing */
/* discriminant */ 0,
DayOfWeek::Tuesday
/* discriminant */ 1,
EnumWithEverything::Default
/* nothing */
/* discriminant */ 0,
EnumWithEverything::Today(
DayOfWeek::Monday
)

/* discriminant */ 1,
/* DayOfWeek discriminant */ 0
EnumWithEverything::Today(
DayOfWeek::Friday
)

/* discriminant */ 1,
/* DayOfWeek discriminant */ 4
EnumWithEverything::Write(
Vec::new(),
0,
)

/* discriminant */ 2,
/* vec length */ 0, 0, 0, 0,
/* u16 */ 0, 0,
EnumWithEverything::Write(
[1, 2, 3].to_vec(),
4
)

/* discriminant */ 2,
/* vec length */ 0, 0, 0, 3,
/* vec contents */ 1, 2, 3,
/* an extra 16 */ 0, 4,
EnumWithEverything::Struct (
int: 0x42,
seq: vec![0x1, 0x2, 0x3, 0x4, 0x5],
another_byte: 0x6,
uint_32: 0x12345,
uint_64: 0x123456789,
);

/* discriminant */ 3,
/* int */ 0, 0x42,
/* seq length */ 0, 0, 0, 5,
/* seq contents */ 1, 2, 3, 4, 5,
/* another_byte */ 6,
/* uint_32 */ 0x00, 0x01, 0x23, 0x45,
/* uint_64 */ 0x00, 0x00, 0x00, 0x01,
0x23, 0x45, 0x67, 0x89,