Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ask! Tuple & Enum Support (Experimental) #260

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

ashutoshvarma
Copy link
Contributor

@ashutoshvarma ashutoshvarma commented Feb 20, 2023

Changes

  • Add Tuple & Enum Variant support in ask-transform's Metadata vistitor.
  • Add debugMessage() in env for debugging (e0e2260)

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 :-

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 :-

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 - ashutoshvarma@8671900.
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

  • Add support for Tuple in metadata
  • Add support for Enum in metadata
  • Add support for serialize() & packedLayout() decorators for Enum
  • Handle empty variants in better way

@ashutoshvarma
Copy link
Contributor Author

ashutoshvarma commented Feb 20, 2023

@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.

@yjhmelody yjhmelody added enhancement New feature or request feature New feature labels Feb 21, 2023
@yjhmelody
Copy link
Contributor

Ok, I will take a look at this. It seems a good idea to decorator a class to be tuple or someelse other.

@yjhmelody
Copy link
Contributor

yjhmelody commented Feb 21, 2023

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.

@yjhmelody
Copy link
Contributor

@ashutoshvarma Hi, I would like to implement tuple and enum in serde-as side. It will be more generic.

@ashutoshvarma
Copy link
Contributor Author

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:-

@yjhmelody
Copy link
Contributor

yjhmelody commented Mar 2, 2023

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.

@yjhmelody
Copy link
Contributor

yjhmelody commented Mar 2, 2023

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

@ashutoshvarma
Copy link
Contributor Author

ashutoshvarma commented Mar 30, 2023

@yjhmelody friendly ping, how's the work on serde side going?

@yjhmelody
Copy link
Contributor

@yjhmelody friendly ping, how's the work on serde side going?

It's being done slowly...

@ashutoshvarma
Copy link
Contributor Author

Cool! Let me know if I can be of any help to accelerate this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request feature New feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants