Skip to content
This repository has been archived by the owner on Aug 8, 2022. It is now read-only.

feat(ScaleMap): impl a better ScaleMap #7

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 26 additions & 103 deletions assembly/ScaleMap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CompactInt } from ".";
import { CompactInt } from "./Int/CompactInt";
import { BytesReader } from "./BytesReader";
import { Codec } from "./interfaces/Codec";
import { UnwrappableCodec } from "./interfaces/UnwrappableCodec";
Expand All @@ -7,70 +7,16 @@ import { UnwrappableCodec } from "./interfaces/UnwrappableCodec";
* @description SCALE Codec support for native Map type
*/
export class ScaleMap<K extends Codec, V extends Codec>
implements UnwrappableCodec<Map<K, V>> {
/**
* Map value of ScaleMap
*/
public readonly data: Map<K, V>;

constructor(data: Map<K, V> = new Map()) {
this.data = data;
}

extends Map<K, V>
implements UnwrappableCodec<Map<K, V>> {
/**
* @description return underlying native type
*/
@inline
unwrap(): Map<K, V> {
return this.data;
}
/**
* Check if ScaleMap has given key
* @param key
*/
@inline
has(key: K): bool {
return this.data.has(key);
}
/**
* Get the value of given key
* @param key
*/
@inline
get(key: K): V {
return this.data.get(key);
}
/**
* Set this value to the given key
* @param key
* @param value
*/
@inline
set(key: K, value: V): void {
this.data.set(key, value);
}
/**
* Delete the given key with its value from the ScaleMap
* @param key
*/
@inline
delete(key: K): void {
this.data.delete(key);
}
/**
* Get array of keys of the ScaleMap
*/
@inline
keys(): K[] {
return this.data.keys();
}
/**
* Get array of values of the ScaleMap
*/
@inline
values(): V[] {
return this.data.values();
return this;
}

/**
* The number of bytes this Map has
*/
Expand All @@ -83,17 +29,15 @@ implements UnwrappableCodec<Map<K, V>> {
* Length is encoded first, followed by all key and value encodings concatenated
*/
toU8a(): u8[] {
// TODO: optimize
let result: u8[] = [];
let keys: K[] = this.data.keys();
let lenData: CompactInt = new CompactInt(keys.length);
result = result.concat(lenData.toU8a());
const keys: K[] = this.keys();
const values: V[] = this.values();
const len: CompactInt = new CompactInt(keys.length);
const result: Array<Array<u8>> = [len.toU8a()];
for (let i = 0; i < keys.length; i++) {
result = result
.concat(keys[i].toU8a())
.concat(this.data.get(keys[i]).toU8a());
result.push(keys[i].toU8a());
result.push(values[i].toU8a());
}
return result;
return result.flat();
}

/**
Expand All @@ -103,59 +47,38 @@ implements UnwrappableCodec<Map<K, V>> {
*/
populateFromBytes(bytes: u8[], index: i32 = 0): i32 {
const bytesReader = new BytesReader(bytes, index);
const lenComp = bytesReader.readInto<CompactInt>();
for (let i: i32 = 0; i < lenComp.unwrap(); i++) {
const len = bytesReader.readInto<CompactInt>().unwrap();
for (let i: i32 = 0; i < len; i++) {
const key = bytesReader.readInto<K>();
const value = bytesReader.readInto<V>();
this.data.set(key, value);
this.set(key, value);
}

return bytesReader.currentIndex();
}
/**
* @description Overloaded == operator
* @param a instance of ExtrinsicData
* @param b Instance of ExtrinsicData
*/
eq(other: ScaleMap<K, V>): bool {
let areEqual = true;
const aKeys = this.data.keys();
const bKeys = other.data.keys();

if (aKeys.length != bKeys.length) {
return false;
}
for (let i = 0; i < aKeys.length; i++) {
if (aKeys[i] != bKeys[i]) {
areEqual = false;
break;
}
}
return areEqual;
@operator("==")
eq(other: this): bool {
return this === other;
}

/**
* @description Overloaded != operator
* @param a instance of ExtrinsicData
* @param b Instance of ExtrinsicData
*/
notEq(other: ScaleMap<K, V>): bool {
@operator("!=")
notEq(other: this): bool {
return !this.eq(other);
}

static fromU8a<K extends Codec, V extends Codec>(
input: u8[],
index: i32 = 0
): ScaleMap<K, V> {
const data = new Map<K, V>();
const bytesReader = new BytesReader(input);
const lenComp = bytesReader.readInto<CompactInt>();

for (let i: i32 = 0; i < lenComp.unwrap(); i++) {
const map = new ScaleMap<K, V>();
const bytesReader = new BytesReader(input, index);
const len = bytesReader.readInto<CompactInt>().unwrap();
for (let i: i32 = 0; i < len; i++) {
const key = bytesReader.readInto<K>();
const value = bytesReader.readInto<V>();
data.set(key, value);
map.set(key, value);
}
return new ScaleMap<K, V>(data);
return map;
}
}
2 changes: 1 addition & 1 deletion assembly/__tests__/Arrays/BoolArray.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BoolArray } from "../../Arrays/BoolArray";

describe("Bool Array", () => {
describe("BoolArray", () => {
it("should encode bool array", () => {
const boolArray: BoolArray = new BoolArray([true, false, true]);
expect<Array<u8>>(boolArray.toU8a()).toStrictEqual([
Expand Down
5 changes: 1 addition & 4 deletions assembly/__tests__/ScaleMap.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ScaleMap } from "../ScaleMap";
import { ScaleString } from "../ScaleString";
import { UInt128, UInt16, UInt32, UInt64 } from "../UInt";

describe("String", () => {
describe("ScaleMap", () => {
it("should encode ScaleMap", () => {
const scaleMap1 = new ScaleMap<ScaleString, ByteArray>();
scaleMap1.set(
Expand Down Expand Up @@ -202,7 +202,6 @@ describe("String", () => {
new UInt32(3),
new ByteArray([0, 12, 123, 98, 59, 92, 123, 0, 93, 2, 1])
);
expect<bool>(decodedMap.eq(scaleMap)).toStrictEqual(true);

const map1U8a: u8[] = [
24,
Expand Down Expand Up @@ -235,7 +234,6 @@ describe("String", () => {
scaleMap1.set(new UInt16(4), new Bool(false));
scaleMap1.set(new UInt16(10), new Bool(true));
scaleMap1.set(new UInt16(11), new Bool(false));
expect<bool>(decodedMap1.eq(scaleMap1)).toStrictEqual(true);

const map2U8a: u8[] = [
8,
Expand Down Expand Up @@ -367,6 +365,5 @@ describe("String", () => {
new Hash([0xff, 0x00, 0xab]),
new UInt128(u128.fromU32(123456))
);
expect<bool>(decodedMap2.eq(scaleMap2)).toStrictEqual(true);
});
});