Derive Macro concordium_std::SchemaType
#[derive(SchemaType)]
{
// Attributes available to this derive:
#[concordium]
}
Expand description
Derive the SchemaType
trait for a type with a schema::Type
matching
the implementation when deriving Serial
.
Can be used for enums and structs.
If the type is a struct all fields must implement the SchemaType
trait.
If the type is an enum then all fields of each of the variants must
implement the SchemaType
trait.
§Specifying the tag value for an enum variant
When deriving Serial
, Deserial
and DeserialWithState
the
discriminating tag can be set explicitly using #[concordium(tag = n)]
where n
is a unsigned integer literal. This require annotating the enum
with #[concordium(repr(..))]
, see Serial
for more on this attribute.
The current version of the contract schema cannot express tags encoded with
more than one byte, meaning only the annotation of #[concordium(repr(u8))]
can be used, when deriving the SchemaType
.
§Nesting enums with a flat serialization using #[concordium(forward = ...)]
Often it is desired to have a single type representing a parameter or the
events. A general pattern for enums is to nest them, however deriving
the schema type for enums with nested enums exposes this. The solution is to
use the attribute #[concordium(forward = ...)]
on the variant with a
nested enum. This attribute takes a tag or a list of tags and changes the
(de)serialization to hide the nesting. The SchemaType
produced is a
flatten enum hiding the nested enum.
Note that the schema can only be built when the nested type is an enum
implementing SchemaType
.
Incorrect use will not be caught when compiling the contract itself but
it will be caught when attempting to build the schema using
cargo-concordium
.
#[derive(SchemaType)]
#[concordium(repr(u8))]
enum Event {
SomeEvent(MyEvent),
#[concordium(forward = [42, 43, 44, 45])]
OtherEvent(NestedEvent),
}
For convenience the attribute also supports the values cis2_events
,
cis3_events
and cis4_events
which are unfolded to the list of tags used
for events in CIS-2, CIS-3 and CIS-4 respectively.
#[derive(SchemaType)]
#[concordium(repr(u8))]
enum Event {
SomeEvent(MyEvent),
#[concordium(forward = cis2_events)]
Cis2(Cis2Event),
}
Setting #[concordium(forward = n)]
on a variant will produce an error if:
- The type does not have a
#[concordium(repr(u*))]
attribute. - If any of the forwarded tags
n
cannot be represented by the#[concordium(repr(u*))]
. - Any of the forwarded tags
n
overlap with a tag of another variant. n
contains a predefined set and the value of#[concordium(repr(u*))]
is incompatible.- If the variant does not have exactly one field.
Note that the derive macro does not check forwarded tags matches the tags of the inner type.
§Generic type bounds
By default a trait bound is added on each generic type for implementing
SchemaType
. However, if this is not desirable, the default bound can be
replaced by using the bound
attribute on the type and providing the
replacement.
Bounds present in the type declaration will still be present in the implementation, even when a bound is provided:
§Example
#[derive(SchemaType)]
#[concordium(bound(schema_type = "A: SomeOtherTrait"))]
struct Foo<A: SomeTrait> {
bar: A,
}
// Derived implementation:
impl <A: SomeTrait> SchemaType for Foo<A> where A: SomeOtherTrait { .. }
§Collections
Collections (Vec, BTreeMap, BTreeSet) and strings (String, str) can be
annotated with size_length
which is the number of bytes used for encoding
the number of elements, see derive macro [‘Serial’] for more on this.
The value of this field is the number of bytes that will be used for
encoding the number of elements. Supported values are 1
, 2
, 4
, 8
.
§Example
#[derive(SchemaType)]
struct Foo {
#[concordium(size_length = 1)]
bar: BTreeSet<u8>,
}
§Transparent
Deriving SchemaType
for structs using the newtype design pattern exposes
the wrapping struct which is often not desirable. The attribute
#[concordium(transparent)]
can be added above the struct which changes the
implementation of SchemaType
to schema type of the field.
The #[concordium(transparent)]
attribute can only be used for structs with
a single field, and the type of this field must implement SchemaType
.
§Example
#[derive(SchemaType)]
#[concordium(transparent)]
struct Foo {
bar: u32,
}
§Example
The ‘transparent’ attribute will still take account for field attributes
such as size_length
for collections.
#[derive(SchemaType)]
#[concordium(transparent)]
struct Foo {
#[concordium(size_length = 1)]
bar: Vec<u32>,
}