near / borsh-js

TypeScript/JavaScript implementation of Binary Object Representation Serializer for Hashing
Apache License 2.0
112 stars 38 forks source link

Define Schema using decorators #39

Closed marcus-pousette closed 10 months ago

marcus-pousette commented 2 years ago

Why?

Changes:

Todos (maybe):

See tests for all examples, but just a few examples:

Enum, variant at instruction "slot" 1.

import { generateSchemas, StructKind, Field, Variant } from "../schema";

@Variant(1)
class TestEnum {
    @Field({ type: 'u8' })
    public a: number;

    constructor(a: number) {
        this.a = a

    }
}

class TestStruct {
    @Field({ type: TestEnum })
    public enum: TestEnum;

    constructor(value: TestEnum) {
        this.enum = value
    }
}
const instance = new TestStruct(new TestEnum(4));
const generatedSchemas = generatesSchema([TestStruct])
const buf = serialize(generatedSchemas, instance);
expect(buf).toEqual(Buffer.from([1, 4]));

Nested Schema generation for structs

import { generateSchemas, StructKind, Field } from "../schema";

class InnerStruct {
    @Field({ type: 'typeB' })
    public b: number;

}

class TestStruct {
    @Field({ type: InnerStruct })
    public a: InnerStruct;

}

const generatedSchemas = generateSchemas([TestStruct])
expect(generatedSchemas.get(TestStruct)).toEqual({
    kind: 'struct',
    fields: [
        ['a', InnerStruct],
    ]
});
expect(generatedSchemas.get(InnerStruct)).toEqual({
    kind: 'struct',
    fields: [
        ['b', 'typeB'],
    ]
});

Option

import { generateSchemas, StructKind, Field } from "../schema";

class TestStruct {
  @Field({ type: 'u8', option: true })
  public a: number;

}
const schema: StructKind = generateSchemas([TestStruct]).get(TestStruct)
expect(schema).toEqual({
  fields: [
      [
          "a",
          {
              kind: 'option',
              type: 'u8'
          },
      ]
  ],
  kind: "struct",
});

Explicit serialization order of fields

import { generateSchemas, StructKind, Field } from "../schema";

class TestStruct {
    @Field({ type: 'u8', index: 1 })
    public a: number;

    @Field({ type: 'u8', index: 0 })
    public b: number;
}
const schema: StructKind = generateSchemas([TestStruct]).get(TestStruct)
expect(schema).toEqual({
    fields: [
        [
            "b",
            "u8",
        ],
        [
            "a",
            "u8",
        ],
    ],
    kind: "struct",
});

Please let me know (quite quickly) if you want these kinds of ergonomics in the library. If so, and you are actively working on this repository, I will put some more time this week into this PR.

dgabriele commented 2 years ago

Any update on this? Would be great to serialize enums like this.

ailisp commented 1 year ago

I think our decision is to have a JS compatible borsh, so TS decorators won't fit our goal. But that's not to say it's not a good approach. For new comers who use TS, @marcus-pousette implemented https://github.com/dao-xyz/borsh-ts is a great library that you can consider. If you also need to use borsh in JS, then near/borsh-js is for you.

gagdiez commented 10 months ago

closing this PR since a different approach was maintained, and anyway the use of enums has been simplified.