Vector extends Array (#404)
* Vector extends Array * Update tests * Add tests for Vector * Remove .get on Vector * Change back toString representation
This commit is contained in:
@@ -53,7 +53,7 @@ describe('Justification', () => {
|
||||
});
|
||||
|
||||
it('has the correct signatures', () => {
|
||||
const sig = just.signatures.get(1);
|
||||
const sig = just.signatures[1];
|
||||
|
||||
expect(sig.authorityId.toHex()).toEqual('0x9876');
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ describe('Digest', () => {
|
||||
|
||||
expect(digest.logs.length).toEqual(1);
|
||||
|
||||
const log = digest.logs.get(0);
|
||||
const log = digest.logs[0];
|
||||
|
||||
expect(log.type).toBe('Seal');
|
||||
expect(log.value.toJSON()).toEqual([
|
||||
|
||||
@@ -21,7 +21,7 @@ describe('EventRecord', () => {
|
||||
|
||||
it('decodes correctly', () => {
|
||||
const records: Vector<EventRecord> = createType('Vec<EventRecord>', json1.params.result.changes[0][1]) as any;
|
||||
const er = records.get(0);
|
||||
const er = records[0];
|
||||
|
||||
expect(er.phase.type).toEqual('ApplyExtrinsic');
|
||||
});
|
||||
@@ -31,7 +31,7 @@ describe('EventRecord', () => {
|
||||
|
||||
expect(records).toHaveLength(4);
|
||||
|
||||
const er = records.get(2);
|
||||
const er = records[2];
|
||||
|
||||
expect(
|
||||
er.event.data.toArray().map((v) => v.toString())
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('RuntimeVersion', () => {
|
||||
});
|
||||
|
||||
it('has the apis', () => {
|
||||
const api = version.apis.get(0);
|
||||
const api = version.apis[0];
|
||||
|
||||
expect(api.id.toHex()).toEqual('0x696e686572656e74');
|
||||
expect(api.version.toNumber()).toEqual(1);
|
||||
|
||||
@@ -35,8 +35,8 @@ describe('SignedBlock', () => {
|
||||
const s = new SignedBlock(events.result);
|
||||
|
||||
expect(s.block.header.digest.logs.length).toBe(1);
|
||||
expect(s.block.header.digest.logs.get(0).type).toBe('AuthoritiesChange');
|
||||
expect(s.block.header.digest.logs.get(0).value.toJSON()).toEqual([
|
||||
expect(s.block.header.digest.logs[0].type).toBe('AuthoritiesChange');
|
||||
expect(s.block.header.digest.logs[0].value.toJSON()).toEqual([
|
||||
'5EyrU8k6worwXWfW2LajRvS7XF6eta286tMpHeHUwMPpzQ9F',
|
||||
'5Dpq7rU6KAZVdRtcegvpCoeJtZzFPzieRkRz4xajRAiMRkCf',
|
||||
'5CCtQPAYtuDXt6H4WMrn5nFNk4gemkVRD3k1r1mA7YiZLPBq',
|
||||
@@ -55,14 +55,14 @@ describe('SignedBlock', () => {
|
||||
});
|
||||
|
||||
it('has the correct data for the first', () => {
|
||||
const x = extrinsics.get(0);
|
||||
const x = extrinsics[0];
|
||||
|
||||
expect(x.callIndex).toEqual(new Uint8Array([2, 0]));
|
||||
expect(x.method.args[0].toU8a()).toEqual(new Uint8Array([70, 41, 195, 91, 0, 0, 0, 0]));
|
||||
});
|
||||
|
||||
it('has the correct data for the second', () => {
|
||||
const x = extrinsics.get(1);
|
||||
const x = extrinsics[1];
|
||||
|
||||
expect(x.callIndex).toEqual(new Uint8Array([1, 0]));
|
||||
expect(x.method.args[0].toString()).toEqual('5CPaGq4KcmntaboAxg5nyqGXdyzaBV2hj6PvhNA3syigiRg8');
|
||||
|
||||
@@ -20,7 +20,7 @@ describe('StorageChangeSet', () => {
|
||||
|
||||
it('wraps key/value', () => {
|
||||
expect(
|
||||
set.changes.get(0).value.toString()
|
||||
set.changes[0].value.toString()
|
||||
).toEqual('0xcd');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,30 +4,35 @@
|
||||
|
||||
import extrinsics from '@polkadot/extrinsics/static';
|
||||
|
||||
import AccountId from '../AccountId';
|
||||
import { Codec, CodecTo } from '../types';
|
||||
import createType from './createType';
|
||||
import Method from '../Method';
|
||||
import PropIndex from '../PropIndex';
|
||||
import Proposal from '../Proposal';
|
||||
import Text from '../Text';
|
||||
import Vector from './Vector';
|
||||
import Tuple from './Tuple';
|
||||
|
||||
describe('Vector', () => {
|
||||
let array;
|
||||
let vector: Vector<Codec>;
|
||||
|
||||
beforeEach(() => {
|
||||
array = new Vector(Text, ['1', '23', '345', '4567', new Text('56789')]);
|
||||
vector = new Vector(Text, ['1', '23', '345', '4567', new Text('56789')]);
|
||||
|
||||
Method.injectExtrinsics(extrinsics);
|
||||
});
|
||||
|
||||
it('wraps a sequence of values', () => {
|
||||
expect(array.length).toEqual(5); // eslint-disable-line
|
||||
expect(vector.length).toEqual(5); // eslint-disable-line
|
||||
});
|
||||
|
||||
it('has a sane representation for toString', () => {
|
||||
expect(array.toString()).toEqual('[1, 23, 345, 4567, 56789]');
|
||||
expect(vector.toString()).toEqual('[1, 23, 345, 4567, 56789]');
|
||||
});
|
||||
|
||||
it('encodes with length prefix', () => {
|
||||
expect(array.toU8a()).toEqual(new Uint8Array([
|
||||
expect(vector.toU8a()).toEqual(new Uint8Array([
|
||||
5 << 2,
|
||||
1 << 2, 49,
|
||||
2 << 2, 50, 51,
|
||||
@@ -39,36 +44,36 @@ describe('Vector', () => {
|
||||
|
||||
it('allows contruction via JSON', () => {
|
||||
expect(
|
||||
new Vector(Text, ['6', '7']).toString()
|
||||
).toEqual('[6, 7]');
|
||||
new Vector(Text, ['6', '7']).toJSON()
|
||||
).toEqual(['6', '7']);
|
||||
});
|
||||
|
||||
it('exposes the type', () => {
|
||||
expect(array.Type).toEqual('Text');
|
||||
expect(vector.Type).toEqual('Text');
|
||||
});
|
||||
|
||||
it('decodes a complex type via construction', () => {
|
||||
const test = createType('Vec<(PropIndex, Proposal, AccountId)>', new Uint8Array([
|
||||
4, 10, 0, 0, 0, 0, 3, 80, 123, 10, 9, 34, 48, 120, 52, 50, 34, 58, 32, 34, 48, 120, 52, 51, 34, 10, 125, 10, 209, 114, 167, 76, 218, 76, 134, 89, 18, 195, 43, 160, 168, 10, 87, 174, 105, 171, 174, 65, 14, 92, 203, 89, 222, 232, 78, 47, 68, 50, 219, 79
|
||||
]));
|
||||
const first = test.get(0);
|
||||
const first = (test as Vector<Codec>)[0] as Tuple;
|
||||
|
||||
expect(first.getAtIndex(0).toNumber()).toEqual(10);
|
||||
expect(first.getAtIndex(1).callIndex).toEqual(new Uint8Array([0, 3]));
|
||||
expect(first.getAtIndex(2).toString()).toEqual('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ');
|
||||
expect((first.getAtIndex(0) as PropIndex).toNumber()).toEqual(10);
|
||||
expect((first.getAtIndex(1) as Proposal).callIndex).toEqual(new Uint8Array([0, 3]));
|
||||
expect((first.getAtIndex(2) as AccountId).toString()).toEqual('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ');
|
||||
});
|
||||
|
||||
describe('array-like functions', () => {
|
||||
describe('vector-like functions', () => {
|
||||
it('allows retrieval of a specific item', () => {
|
||||
expect(
|
||||
array.get(2).toString()
|
||||
vector[2].toString()
|
||||
).toEqual('345');
|
||||
});
|
||||
|
||||
it('exposes a working forEach', () => {
|
||||
const result = {};
|
||||
const result: { [index: number]: string } = {};
|
||||
|
||||
array.forEach((e, i) => {
|
||||
vector.forEach((e, i) => {
|
||||
result[i] = e.toString();
|
||||
});
|
||||
|
||||
@@ -83,20 +88,32 @@ describe('Vector', () => {
|
||||
|
||||
it('exposes a working filter', () => {
|
||||
expect(
|
||||
array.filter((e, i) => i >= 3).toString()
|
||||
vector.filter((e, i) => i >= 3).toString()
|
||||
).toEqual('4567,56789');
|
||||
});
|
||||
|
||||
it('exposes a working map', () => {
|
||||
expect(
|
||||
array.map((e) => e.toString().substr(0, 1))
|
||||
vector.map((e) => e.toString().substr(0, 1))
|
||||
).toEqual(['1', '2', '3', '4', '5']);
|
||||
});
|
||||
|
||||
it('exposes a working reduce', () => {
|
||||
expect(
|
||||
array.reduce((r, e) => `${r}${e}`, '')
|
||||
vector.reduce((r, e) => `${r}${e}`, '')
|
||||
).toEqual('123345456756789');
|
||||
});
|
||||
});
|
||||
|
||||
describe('encode', () => {
|
||||
const testEncode = (to: CodecTo, expected: any) =>
|
||||
it(`can encode ${to}`, () => {
|
||||
expect(vector[to]()).toEqual(expected);
|
||||
});
|
||||
|
||||
testEncode('toHex', '0x1404310832330c3334351034353637143536373839');
|
||||
testEncode('toJSON', ['1', '23', '345', '4567', '56789']);
|
||||
testEncode('toString', '[1, 23, 345, 4567, 56789]');
|
||||
testEncode('toU8a', Uint8Array.from([20, 4, 49, 8, 50, 51, 12, 51, 52, 53, 16, 52, 53, 54, 55, 20, 53, 54, 55, 56, 57]));
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
import { u8aConcat, u8aToU8a, u8aToHex } from '@polkadot/util';
|
||||
|
||||
import Base from './Base';
|
||||
import Compact, { DEFAULT_LENGTH_BITS } from './Compact';
|
||||
import { Codec, Constructor } from '../types';
|
||||
|
||||
@@ -15,12 +14,12 @@ import { Codec, Constructor } from '../types';
|
||||
// `reduce` is exposed on the interface.
|
||||
export default class Vector<
|
||||
T extends Codec
|
||||
> extends Base<Array<T>> implements Codec {
|
||||
> extends Array<T> implements Codec {
|
||||
private _Type: Constructor<T>;
|
||||
|
||||
constructor (Type: Constructor<T>, value: Vector<any> | Uint8Array | string | Array<any> = [] as Array<any>) {
|
||||
super(
|
||||
Vector.decodeVector(Type, value)
|
||||
...Vector.decodeVector(Type, value)
|
||||
);
|
||||
|
||||
this._Type = Type;
|
||||
@@ -33,8 +32,6 @@ export default class Vector<
|
||||
? entry
|
||||
: new Type(entry)
|
||||
);
|
||||
} else if (value instanceof Vector) {
|
||||
return Vector.decodeVector(Type, value.raw);
|
||||
}
|
||||
|
||||
const u8a = u8aToU8a(value);
|
||||
@@ -66,42 +63,14 @@ export default class Vector<
|
||||
return this._Type.name;
|
||||
}
|
||||
|
||||
get length (): number {
|
||||
return this.raw.length;
|
||||
}
|
||||
|
||||
get encodedLength (): number {
|
||||
return this.raw.reduce((total, raw) => {
|
||||
return this.reduce((total, raw) => {
|
||||
return total + raw.encodedLength;
|
||||
}, Compact.encodeU8a(this.length, DEFAULT_LENGTH_BITS).length);
|
||||
}
|
||||
|
||||
filter (fn: (item: T, index: number) => any): Array<T> {
|
||||
return this.raw.filter(fn);
|
||||
}
|
||||
|
||||
find (fn: (item: T, index: number) => any): T | undefined {
|
||||
return this.raw.find(fn);
|
||||
}
|
||||
|
||||
forEach (fn: (item: T, index: number) => any): any {
|
||||
return this.raw.forEach(fn);
|
||||
}
|
||||
|
||||
get (index: number): T {
|
||||
return this.raw[index];
|
||||
}
|
||||
|
||||
map<O> (fn: (item: T, index: number) => O): Array<O> {
|
||||
return this.raw.map(fn);
|
||||
}
|
||||
|
||||
push (item: T): void {
|
||||
this.raw.push(item);
|
||||
}
|
||||
|
||||
reduce<O> (fn: (result: O, item: T, index: number) => O, initial: O): O {
|
||||
return this.raw.reduce(fn, initial);
|
||||
toArray (): Array<T> {
|
||||
return Array.from(this);
|
||||
}
|
||||
|
||||
toHex (): string {
|
||||
@@ -109,13 +78,22 @@ export default class Vector<
|
||||
}
|
||||
|
||||
toJSON (): any {
|
||||
return this.raw.map((entry) =>
|
||||
return this.map((entry) =>
|
||||
entry.toJSON()
|
||||
);
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
// Overwrite the default toString representation of Array.
|
||||
const data = this.map((entry) =>
|
||||
entry.toString()
|
||||
);
|
||||
|
||||
return `[${data.join(', ')}]`;
|
||||
}
|
||||
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
const encoded = this.raw.map((entry) =>
|
||||
const encoded = this.map((entry) =>
|
||||
entry.toU8a(isBare)
|
||||
);
|
||||
|
||||
@@ -127,11 +105,15 @@ export default class Vector<
|
||||
);
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
const data = this.raw.map((entry) =>
|
||||
entry.toString()
|
||||
);
|
||||
// Below are methods that we override. When we do a `new Vector(...).map()`,
|
||||
// we want it to return an Array. We only override the methods that return a
|
||||
// new instance.
|
||||
|
||||
return `[${data.join(', ')}]`;
|
||||
filter (callbackfn: (value: T, index: number, array: Array<T>) => any, thisArg?: any): Array<T> {
|
||||
return this.toArray().filter(callbackfn, thisArg);
|
||||
}
|
||||
|
||||
map<U> (callbackfn: (value: T, index: number, array: Array<T>) => U, thisArg?: any): Array<U> {
|
||||
return this.toArray().map(callbackfn, thisArg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user