VecFixed with hex inputs (& adjust isPedantic) (#3522)

* VecFixed with hex inputs (& adjust isPedantic)

* Update packages/types/src/codec/VecFixed.spec.ts

* Cleanups
This commit is contained in:
Jaco
2021-05-13 09:08:52 +02:00
committed by GitHub
parent a04ccec445
commit 121bfc7913
6 changed files with 56 additions and 42 deletions
+5 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import { TypeRegistry } from '../create';
import { Text } from '../primitive';
import { Text, u16 } from '../primitive';
import { VecFixed } from '.';
describe('VecFixed', (): void => {
@@ -17,6 +17,10 @@ describe('VecFixed', (): void => {
expect(new VecFixed(registry, Text, 2, new Uint8Array([0x00, 0x04, 0x31])).toHex()).toEqual('0x000431');
});
it('constructs via hex', (): void => {
expect(new VecFixed(registry, u16, 2, '0x12345678').toHex()).toEqual('0x12345678');
});
it('decodes reusing instance inputs', (): void => {
const foo = new Text(registry, 'bar');
+21 -21
View File
@@ -3,12 +3,31 @@
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { assert, compactToU8a, isU8a, u8aConcat } from '@polkadot/util';
import { assert, compactToU8a, isHex, isU8a, u8aConcat } from '@polkadot/util';
import { AbstractArray } from './AbstractArray';
import { typeToConstructor } from './utils';
import { Vec } from './Vec';
/** @internal */
function decodeVecFixed<T extends Codec> (registry: Registry, Type: Constructor<T>, allocLength: number, value: VecFixed<any> | Uint8Array | string | any[]): T[] {
const values = Vec.decodeVec(
registry,
Type,
isU8a(value) || isHex(value)
? u8aConcat(compactToU8a(allocLength), value)
: value
);
while (values.length < allocLength) {
values.push(new Type(registry));
}
assert(values.length === allocLength, () => `Expected a length of exactly ${allocLength} entries`);
return values;
}
/**
* @name VecFixed
* @description
@@ -20,30 +39,11 @@ export class VecFixed<T extends Codec> extends AbstractArray<T> {
constructor (registry: Registry, Type: Constructor<T> | keyof InterfaceTypes, length: number, value: VecFixed<any> | Uint8Array | string | any[] = [] as any[]) {
const Clazz = typeToConstructor<T>(registry, Type);
super(registry, ...VecFixed.decodeVecFixed(registry, Clazz, length, value));
super(registry, ...decodeVecFixed(registry, Clazz, length, value));
this._Type = Clazz;
}
/** @internal */
public static decodeVecFixed<T extends Codec> (registry: Registry, Type: Constructor<T>, allocLength: number, value: VecFixed<any> | Uint8Array | string | any[]): T[] {
const values = Vec.decodeVec(
registry,
Type,
isU8a(value)
? u8aConcat(compactToU8a(allocLength), value)
: value
);
while (values.length < allocLength) {
values.push(new Type(registry));
}
assert(values.length === allocLength, () => `Expected a length of exactly ${allocLength} entries`);
return values;
}
public static with<O extends Codec> (Type: Constructor<O> | keyof InterfaceTypes, length: number): Constructor<VecFixed<O>> {
return class extends VecFixed<O> {
constructor (registry: Registry, value?: any[]) {
+18 -6
View File
@@ -125,20 +125,32 @@ describe('createType', (): void => {
describe('isPedantic', (): void => {
it('correctly decodes Bytes', (): void => {
expect(
createTypeUnsafe(registry, 'Bytes', ['0x12345678'], { isPedantic: true })
).toBeDefined();
createTypeUnsafe(registry, 'Bytes', ['0x12345678'], { isPedantic: true }).toHex()
).toEqual('0x12345678');
});
it('correctly decodes Bytes (prefixed)', (): void => {
expect(
createTypeUnsafe(registry, 'Bytes', [new Uint8Array([4 << 2, 1, 2, 3, 4])], { isPedantic: true })
).toBeDefined();
createTypeUnsafe(registry, 'Bytes', [new Uint8Array([4 << 2, 0x12, 0x34, 0x56, 0x78])], { isPedantic: true }).toHex()
).toEqual('0x12345678');
});
it('correctly decodes Text', (): void => {
expect(
createTypeUnsafe(registry, 'Text', ['0x2070726f7669646572'], { isPedantic: true })
).toBeDefined();
createTypeUnsafe(registry, 'Text', ['0x70726f7669646572'], { isPedantic: true }).toString()
).toEqual('provider');
});
it('correctly decodes Type', (): void => {
expect(
createTypeUnsafe(registry, 'Type', ['0x5665633c75383e'], { isPedantic: true }).toString()
).toEqual('Bytes'); // Vec<u8> -> Bytes
});
it('correctly decodes [u16; 4]', (): void => {
expect(
createTypeUnsafe(registry, '[u16; 4]', ['0x0012002300450067'], { isPedantic: true }).toHex()
).toEqual('0x0012002300450067');
});
});
+8 -12
View File
@@ -16,22 +16,18 @@ interface CreateOptions {
// With isPedantic, actually check that the encoding matches that supplied. This
// is much slower, but verifies that we have the correct types defined
// eslint-disable-next-line @typescript-eslint/ban-types
function checkInstance<T extends Codec = Codec, K extends string = string> (value: Uint8Array, created: FromReg<T, K>): void {
const u8a = created.toU8a();
const rawType = created.toRawType();
// for length-prefixed byte types, just check the length, else the full encoding
const isEqual = ['Bytes', 'Text'].includes(rawType)
? [
// input was via hex, we don't have a prefix
(created as Bytes).length,
// input was raw bytes, we do have a prefix
u8a.length
].includes(value.length)
: u8aEq(value, u8a);
assert(isEqual, () => `${rawType}:: Decoded input doesn't match input, received ${u8aToHex(value, 512)} (${value.length} bytes), created ${u8aToHex(u8a, 512)} (${u8a.length} bytes)`);
assert(
u8aEq(value, u8a) || (
// when length-prefixed from hex, just check the actual length
['Bytes', 'Text', 'Type'].includes(rawType) &&
value.length === (created as Bytes).length
),
() => `${rawType}:: Decoded input doesn't match input, received ${u8aToHex(value, 512)} (${value.length} bytes), created ${u8aToHex(u8a, 512)} (${u8a.length} bytes)`
);
}
// Initializes a type with a value. This also checks for fallbacks and in the cases
+1 -1
View File
@@ -109,7 +109,7 @@ export class Text extends String implements Codec {
* @description Returns a hex string representation of the value
*/
public toHex (): string {
// like with Vec<u8>, when we are encoding to hex, we don't actually add
// like with Vec<u8>, when we are encoding to hex, we don't actually add
// the length prefix (it is already implied by the actual string length)
return u8aToHex(this.toU8a(true));
}