Ask! Tuple & Enum Support (Experimental)
Changes
- Add Tuple & Enum Variant support in
ask-transform's Metadata vistitor. - Add
debugMessage()in env for debugging (https://github.com/ask-lang/ask/pull/260/commits/e0e22609595fc1f8eea5436308cebbe3ba55d784)
Ask! Tuple & Enum Support (Experimental)
AssemblyScript does not supports tuples and tagged-union types (Rust-like enums) and so does ask!.
The Option<T> and Result<T, E> are used extensively inside PSPs along with other enum types.
Therefore having their support in ask! is really important before ask! can be used to onboard new
developers from non Rust background.
Notes :-
- All the types in storage should've no required argument in constructor, see https://github.com/ask-lang/ask/issues/245#issuecomment-1408074629
Tuples
Tuples in ask! are objects anointed with @tuple() decorator. All it does is instruct the metadata generator
to output a Tuple type instead of a Composite one.
Below type is equivalent to Rust's (u64, bool).
@tuple()
class MyTuple {
constructor(public val0: u64 = 0, public val1: bool = false) {}
}
Generic implementations for tuples are provided in 'tuples.ts' and recommended over creating a new tuple type.
Compatibility
-
@serialize()- works fine -
@deserialize()- works fine -
@packedLayout()- works fine -
@spreadLayout()- works fine
Enums
Rust like enums (or tagged union types) can be defined using the combination of @enumeration() and @variant() decorators.
enum MyType {
EmptyVariant,
U8(u8),
WithFields { message: String, index: u64 },
}
enum MyTypeEnum {
EmptyVariant,
U8,
WithFields,
}
@serialize()
@deserialize()
class WithFields {
constructor(public message: string = '', public index: u64 = 0) {}
}
@enumeration()
class MyType {
public type: MyTypeEnum = MyTypeEnum.EmptyVariant;
private constructor() {}
//
// ENUM VARIANTS
//
// Empty variant, to declare empty variant use numeric types
@variant({ name: 'EmptyVariant' })
_empty: u8 = 0;
// Tuple variant, use the tuple types
@variant({ name: 'U8' })
_u8: Tuple1<u8> = instantiateZero<Tuple1<u8>>();
// Composite variants, use normal objects
@variant({ name: 'WithFields' })
_withFields: WithFields = instantiateZero<WithFields>();
//
// Variants Constructors
//
static EmptyVariant(): MyType {
const enum = new MyType();
enum.type = MyTypeEnum.EmptyVariant;
return enum;
}
static U8(val: u8): MyType {
const enum = new MyType();
enum.type = MyTypeEnum.U8;
enum._u8 = val;
return enum;
}
static WithFields(val: WithFields): MyType {
const enum = new MyType();
enum.type = MyTypeEnum.WithFields;
enum._withFields = val;
return enum;
}
//
// Variants Getters
//
U8(): u8 {
return this._u8.val0;
}
WithFields(): WithFields {
return this._withFields;
}
// For Serialization and Packed Layout
// See the other enum examples
}
Other Examples :-
-
Option<T>(adapted fromas-containers) -
Result<T>(adapted fromas-containers) -
Id(from PSP34 Spec) -
PSP34Error(from PSP34 Spec)
Please go though this PSP34 implementation in ask! for understanding more about enum support - https://github.com/ashutoshvarma/psp34-contract/tree/feat/enum/packages/psp34/assembly/psp34
Compatibility
Does not support SpreadLayout because ask! does not have something similar to ink! v0.3's FOOTPRINT. I've experimented with adding that to ask!, you can find it here - https://github.com/ashutoshvarma/ask/commit/8671900c2444bc0babe499373bc80dc20ded96f5.
If using inside a spread layout type, use it with Pack<T>.
-
@serialize()- needs manual implementation -
@deserialize()- needs manual implementation -
@packedLayout()- needs manual implementation -
@spreadLayout()- does not support spread layout at all
TODO
- [x] Add support for Tuple in metadata
- [x] Add support for Enum in metadata
- [ ] Add support for
serialize()&packedLayout()decorators for Enum - [ ] Handle empty variants in better way
@yjhmelody & ask! team, please have a look at this PR and let me know your thoughts. I've marked the PR as draft because I've not added a transform for enums because I want to make sure you guys are comfortable with the design first.
Ok, I will take a look at this. It seems a good idea to decorator a class to be tuple or someelse other.
The import of as-contanier is being considered.
But I want to update deps firstly before all concrete works.
I will open a issue to schedule some works. Thank you for your good idea. I hope I could schedule my time starting some work in the next week.
@ashutoshvarma Hi, I would like to implement tuple and enum in serde-as side. It will be more generic.
Hi, I would like to implement tuple and enum in serde-as side. It will be more generic.
That would be great!
I assume you meant support for serialization of enums & tuples in serde-as as it was not included in this PR (this PR add enum/tuple support at metadata generation level)
For tuples, I think as-serde-scale has decent support for them already as @serialize({ omitName: true }) and @deserialize({ omitName: true }) already works pretty well. See - https://github.com/ashutoshvarma/psp34-contract/blob/feat/enum/packages/common/assembly/tuple.ts
For Enums, I've added manual implementations for serialize() and deserialize() for enums, that might be helpful for developing serde transforms:-
-
PSP34Error- https://github.com/ashutoshvarma/psp34-contract/blob/5df066248f8885c948a37e66d2eb1fc93a86c29b/packages/psp34/assembly/types/errors.ts#L92-L128 -
Id- https://github.com/ashutoshvarma/psp34-contract/blob/5df066248f8885c948a37e66d2eb1fc93a86c29b/packages/psp34/assembly/types/id.ts#L131-L198
For tuples, I think as-serde-scale has decent support for them already as @serialize({ omitName: true }) and @deserialize({ omitName: true }) already works pretty well
Yeah, since scale-codec is a binary format without caring about field name, it should work well.
Defining such as serializeTuple method and use it will be better way.
I will improve serde-as features these weeks.
The specific designs may be considered in implementation.
BTW, omitName: true just means renameAll: "". It is used to reduce wasm code size by set all unused string values to be "" (maybe null).
At ink3.0, they were concerned about code size. But it's not necessary
@yjhmelody friendly ping, how's the work on serde side going?
@yjhmelody friendly ping, how's the work on serde side going?
It's being done slowly...
Cool! Let me know if I can be of any help to accelerate this.