Prototype static init Enum/Set/Struct (#5087)
* Prototype static init Enum/Set/Struct * Adjust (similar, logic extracted - further local testing) * Adjust with latest util (no prototype atm) * Introduce prototype assignment * Old Enum tests * Fix toCallsOnly spread * Adjust * Use objectSpread in derives (decorated objects only) * Adjust * Remove extra map from bag get * Additional spreads * Signer spread * Formatting * typo * Adjust spreads for session * Additional spread * Adjust spread * Formatting * CHANGELOG * Adjust * slice * CHANGELOG
This commit is contained in:
@@ -117,13 +117,16 @@ describe('Enum', (): void => {
|
||||
|
||||
it('has correct isXyz/asXyz (Enum.with)', (): void => {
|
||||
const test = new (Enum.with({ First: Text, Second: U32, Third: U32 }))(registry, { Second: 42 }) as any as { isFirst: boolean; isSecond: boolean; asSecond: U32; isThird: boolean; asThird: never };
|
||||
const asKeys = Object.keys(test).filter((k) => k.startsWith('as'));
|
||||
const isKeys = Object.keys(test).filter((k) => k.startsWith('is'));
|
||||
|
||||
expect(asKeys).toEqual(['asFirst', 'asSecond', 'asThird']);
|
||||
expect(isKeys).toEqual(['isFirst', 'isSecond', 'isThird']);
|
||||
// const asKeys = Object.keys(test).filter((k) => k.startsWith('as'));
|
||||
// const isKeys = Object.keys(test).filter((k) => k.startsWith('is'));
|
||||
|
||||
// expect([isKeys, asKeys]).toEqual([
|
||||
// ['isFirst', 'isSecond', 'isThird'],
|
||||
// ['asFirst', 'asSecond', 'asThird']
|
||||
// ]);
|
||||
|
||||
expect([test.isFirst, test.isSecond, test.isThird]).toEqual([false, true, false]);
|
||||
|
||||
expect(test.asSecond.toNumber()).toEqual(42);
|
||||
expect((): never => test.asThird).toThrow(/Cannot convert 'Second' via asThird/);
|
||||
});
|
||||
|
||||
@@ -223,19 +223,6 @@ export class Enum implements IEnum {
|
||||
}
|
||||
|
||||
public static with (Types: Record<string, string | CodecClass> | Record<string, number> | string[]): EnumCodecClass<Enum> {
|
||||
const keys = Array.isArray(Types)
|
||||
? Types
|
||||
: Object.keys(Types);
|
||||
const asKeys = new Array<string>(keys.length);
|
||||
const isKeys = new Array<string>(keys.length);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const name = stringPascalCase(keys[i]);
|
||||
|
||||
asKeys[i] = `as${name}`;
|
||||
isKeys[i] = `is${name}`;
|
||||
}
|
||||
|
||||
let definition: Definition | undefined;
|
||||
|
||||
// eslint-disable-next-line no-return-assign
|
||||
@@ -243,18 +230,36 @@ export class Enum implements IEnum {
|
||||
definition = d;
|
||||
|
||||
return class extends Enum {
|
||||
constructor (registry: Registry, value?: unknown, index?: number) {
|
||||
super(registry, Types, value, index, { definition, setDefinition });
|
||||
static {
|
||||
const keys = Array.isArray(Types)
|
||||
? Types
|
||||
: Object.keys(Types);
|
||||
const asKeys = new Array<string>(keys.length);
|
||||
const isKeys = new Array<string>(keys.length);
|
||||
|
||||
objectProperties(this, isKeys, (_, i) => this.type === keys[i]);
|
||||
objectProperties(this, asKeys, (k, i): Codec => {
|
||||
if (!this[isKeys[i] as keyof this]) {
|
||||
throw new Error(`Cannot convert '${this.type}' via ${k}`);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const name = stringPascalCase(keys[i]);
|
||||
|
||||
asKeys[i] = `as${name}`;
|
||||
isKeys[i] = `is${name}`;
|
||||
}
|
||||
|
||||
objectProperties(this.prototype, isKeys, (_: string, i: number, self: Enum) =>
|
||||
self.type === keys[i]
|
||||
);
|
||||
|
||||
objectProperties(this.prototype, asKeys, (k: string, i: number, self: Enum): Codec => {
|
||||
if (self.type !== keys[i]) {
|
||||
throw new Error(`Cannot convert '${self.type}' via ${k}`);
|
||||
}
|
||||
|
||||
return this.value;
|
||||
return self.value;
|
||||
});
|
||||
}
|
||||
|
||||
constructor (registry: Registry, value?: unknown, index?: number) {
|
||||
super(registry, Types, value, index, { definition, setDefinition });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -109,18 +109,22 @@ export class CodecSet extends Set<string> implements ISet<string> {
|
||||
}
|
||||
|
||||
public static with (values: SetValues, bitLength?: number): CodecClass<CodecSet> {
|
||||
const keys = Object.keys(values);
|
||||
const isKeys = new Array<string>(keys.length);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
isKeys[i] = `is${stringPascalCase(keys[i])}`;
|
||||
}
|
||||
|
||||
return class extends CodecSet {
|
||||
static {
|
||||
const keys = Object.keys(values);
|
||||
const isKeys = new Array<string>(keys.length);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
isKeys[i] = `is${stringPascalCase(keys[i])}`;
|
||||
}
|
||||
|
||||
objectProperties(this.prototype, isKeys, (_: string, i: number, self: CodecSet) =>
|
||||
self.strings.includes(keys[i])
|
||||
);
|
||||
}
|
||||
|
||||
constructor (registry: Registry, value?: string[] | Set<string> | Uint8Array | BN | number | string) {
|
||||
super(registry, values, value, bitLength);
|
||||
|
||||
objectProperties(this, isKeys, (_, i) => this.strings.includes(keys[i]));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ describe('Struct', (): void => {
|
||||
testDecode('hex', '0x1c62617a7a696e6745000000');
|
||||
testDecode('object', { foo: 'bazzing', bar: 69 });
|
||||
testDecode('Uint8Array', Uint8Array.from([28, 98, 97, 122, 122, 105, 110, 103, 69, 0, 0, 0]));
|
||||
testDecode('Struct.with', new (Struct.with({ foo: 'Text', bar: 'U32' }))(registry, { foo: 'bazzing', bar: 69 }));
|
||||
|
||||
it('decodes null/undefined/empty correctly (& equivalent)', (): void => {
|
||||
const Clazz = Struct.with({
|
||||
|
||||
@@ -130,8 +130,6 @@ export class Struct<
|
||||
}
|
||||
|
||||
public static with<S extends TypesDef> (Types: S, jsonMap?: Map<string, string>): CodecClass<Struct<S>> {
|
||||
const keys = Object.keys(Types);
|
||||
|
||||
let definition: Definition | undefined;
|
||||
|
||||
// eslint-disable-next-line no-return-assign
|
||||
@@ -139,10 +137,16 @@ export class Struct<
|
||||
definition = d;
|
||||
|
||||
return class extends Struct<S> {
|
||||
static {
|
||||
const keys = Object.keys(Types);
|
||||
|
||||
objectProperties(this.prototype, keys, (k: string, _: number, self: Struct) =>
|
||||
self.get(k)
|
||||
);
|
||||
}
|
||||
|
||||
constructor (registry: Registry, value?: unknown) {
|
||||
super(registry, Types, value as HexString, jsonMap, { definition, setDefinition });
|
||||
|
||||
objectProperties(this, keys, (k) => this.get(k));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -154,10 +158,6 @@ export class Struct<
|
||||
return this.#Types[1];
|
||||
}
|
||||
|
||||
public getT <T> (key: string): T {
|
||||
return this.get(key) as unknown as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
@@ -171,20 +171,6 @@ export class Struct<
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the Type description of the structure
|
||||
*/
|
||||
public get Type (): E {
|
||||
const result: Record<string, string> = {};
|
||||
const [Types, keys] = this.#Types;
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
result[keys[i]] = new Types[i](this.registry).toRawType();
|
||||
}
|
||||
|
||||
return result as E;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The length of the value when encoded as a Uint8Array
|
||||
*/
|
||||
@@ -205,6 +191,20 @@ export class Struct<
|
||||
return this.registry.hash(this.toU8a());
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the Type description of the structure
|
||||
*/
|
||||
public get Type (): E {
|
||||
const result: Record<string, string> = {};
|
||||
const [Types, keys] = this.#Types;
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
result[keys[i]] = new Types[i](this.registry).toRawType();
|
||||
}
|
||||
|
||||
return result as E;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Compares the value of the input to see if there is a match
|
||||
*/
|
||||
@@ -214,10 +214,10 @@ export class Struct<
|
||||
|
||||
/**
|
||||
* @description Returns a specific names entry in the structure
|
||||
* @param name The name of the entry to retrieve
|
||||
* @param key The name of the entry to retrieve
|
||||
*/
|
||||
public override get (name: keyof S): Codec | undefined {
|
||||
return super.get(name);
|
||||
public override get (key: keyof S): Codec | undefined {
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,6 +227,13 @@ export class Struct<
|
||||
return this.toArray()[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the a types value by name
|
||||
*/
|
||||
public getT <T> (key: string): T {
|
||||
return super.get(key) as unknown as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns a breakdown of the hex encoding for this Codec
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user