Skip to content

Commit

Permalink
[TS-SDK v2] Adding serializeVector and deserializeVector to SDK v2 (
Browse files Browse the repository at this point in the history
aptos-labs#10347)

* Adding `serializeVector` and `deserializeVector` to serializer.ts and deserializer.ts as well as a unit test for each

* Adding documentation for each function

* Removing redundant line in doc comment

* Removing redundant line in deserializer doc comment too
  • Loading branch information
xbtmatt authored and Poytr1 committed Oct 4, 2023
1 parent de14d81 commit 321464c
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 1 deletion.
32 changes: 32 additions & 0 deletions ecosystem/typescript/sdk_v2/src/bcs/deserializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,36 @@ export class Deserializer {
// It is separate from the `deserialize` instance method defined here in Deserializer.
return cls.deserialize(this);
}

/**
* Deserializes an array of BCS Deserializable values given an existing Deserializer
* instance with a loaded byte buffer.
*
* @param cls The BCS-deserializable class to deserialize the buffered bytes into.
* @example
* // serialize a vector of addresses
* const addresses = new Array<AccountAddress>(
* AccountAddress.fromHexInputRelaxed({ input: "0x1" }),
* AccountAddress.fromHexInputRelaxed({ input: "0x2" }),
* AccountAddress.fromHexInputRelaxed({ input: "0xa" }),
* AccountAddress.fromHexInputRelaxed({ input: "0xb" }),
* );
* const serializer = new Serializer();
* serializer.serializeVector(addresses);
* const serializedBytes = serializer.toUint8Array();
*
* // deserialize the bytes into an array of addresses
* const deserializer = new Deserializer(serializedBytes);
* const deserializedAddresses = deserializer.deserializeVector(AccountAddress);
* // deserializedAddresses is now an array of AccountAddress instances
* @returns an array of deserialized values of type T
*/
deserializeVector<T>(cls: Deserializable<T>): Array<T> {
const length = this.deserializeUleb128AsU32();
const vector = new Array<T>();
for (let i = 0; i < length; i += 1) {
vector.push(this.deserialize(cls));
}
return vector;
}
}
28 changes: 27 additions & 1 deletion ecosystem/typescript/sdk_v2/src/bcs/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,11 +277,37 @@ export class Serializer {
*
* @returns the serializer instance
*/
serialize<T extends Serializable>(value: T) {
serialize<T extends Serializable>(value: T): void {
// NOTE: The `serialize` method called by `value` is defined in `value`'s
// Serializable interface, not the one defined in this class.
value.serialize(this);
}

/**
* Serializes an array of BCS Serializable values to a serializer instance.
* Note that this does not return anything- the bytes are added to the serializer instance's byte buffer.
*
* @param values The array of BCS Serializable values
* @example
* const addresses = new Array<AccountAddress>(
* AccountAddress.fromHexInputRelaxed({ input: "0x1" }),
* AccountAddress.fromHexInputRelaxed({ input: "0x2" }),
* AccountAddress.fromHexInputRelaxed({ input: "0xa" }),
* AccountAddress.fromHexInputRelaxed({ input: "0xb" }),
* );
* const serializer = new Serializer();
* serializer.serializeVector(addresses);
* const serializedBytes = serializer.toUint8Array();
* // serializedBytes is now the BCS-serialized bytes
* // The equivalent value in Move would be:
* // `bcs::to_bytes(&vector<address> [@0x1, @0x2, @0xa, @0xb])`;
*/
serializeVector<T extends Serializable>(values: Array<T>): void {
this.serializeU32AsUleb128(values.length);
values.forEach((item) => {
item.serialize(this);
});
}
}

/**
Expand Down
18 changes: 18 additions & 0 deletions ecosystem/typescript/sdk_v2/tests/unit/deserializer.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

import { Account } from "../../src/api/account";
import { Serializable, Serializer, Deserializer } from "../../src/bcs";
import { AccountAddress } from "../../src/core";

describe("BCS Deserializer", () => {
it("deserializes a non-empty string", () => {
Expand Down Expand Up @@ -130,6 +132,22 @@ describe("BCS Deserializer", () => {
}).toThrow("Reached to the end of buffer");
});

it("deserializes a vector of Deserializable types correctly", () => {
const addresses = new Array<AccountAddress>(
AccountAddress.fromHexInputRelaxed({ input: "0x1" }),
AccountAddress.fromHexInputRelaxed({ input: "0xa" }),
AccountAddress.fromHexInputRelaxed({ input: "0x0123456789abcdef" }),
);
const serializer = new Serializer();
serializer.serializeVector(addresses);
const serializedBytes = serializer.toUint8Array();
const deserializer = new Deserializer(serializedBytes);
const deserializedAddresses = deserializer.deserializeVector(AccountAddress);
addresses.forEach((address, i) => {
expect(address.equals(deserializedAddresses[i])).toBeTruthy();
});
});

it("deserializes a single deserializable class", () => {
// Define the MoveStruct class that implements the Deserializable interface
class MoveStruct extends Serializable {
Expand Down
19 changes: 19 additions & 0 deletions ecosystem/typescript/sdk_v2/tests/unit/serializer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { Serializable, Serializer } from "../../src/bcs/serializer";
import { AccountAddress } from "../../src/core";

describe("BCS Serializer", () => {
let serializer: Serializer;
Expand Down Expand Up @@ -224,6 +225,24 @@ describe("BCS Serializer", () => {
}).toThrow();
});

it("serializes a vector of Serializable types correctly", () => {
const addresses = new Array<AccountAddress>(
AccountAddress.fromHexInputRelaxed({ input: "0x1" }),
AccountAddress.fromHexInputRelaxed({ input: "0xa" }),
AccountAddress.fromHexInputRelaxed({ input: "0x0123456789abcdef" }),
);
const serializer = new Serializer();
serializer.serializeVector(addresses);
const serializedBytes = serializer.toUint8Array();
expect(serializedBytes).toEqual(
new Uint8Array([
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0a, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
]),
);
});

it("serializes multiple Serializable values", () => {
class MoveStructA extends Serializable {
constructor(
Expand Down

0 comments on commit 321464c

Please sign in to comment.