Allow for fallback types (struct-only as a start) (#3714)

* Allow for fallback types (struct-only as a start)

* Filter fallback & alias from structs

* Don't clobber existing fallbackType
This commit is contained in:
Jaco
2021-07-01 12:54:02 +02:00
committed by GitHub
parent be2f34a045
commit 6322913310
8 changed files with 55 additions and 7 deletions
+11 -2
View File
@@ -175,7 +175,7 @@ const infoMapping: Record<TypeDefInfo, (registry: Registry, value: TypeDef) => C
// Returns the type Class for construction
export function getTypeClass<T extends Codec = Codec> (registry: Registry, value: TypeDef): Constructor<T> {
const Type = registry.get<T>(value.type);
let Type = registry.get<T>(value.type);
if (Type) {
return Type;
@@ -185,5 +185,14 @@ export function getTypeClass<T extends Codec = Codec> (registry: Registry, value
assert(getFn, () => `Unable to construct class from ${stringify(value)}`);
return getFn(registry, value) as Constructor<T>;
Type = getFn(registry, value) as Constructor<T>;
// don't clobber any existing
if (!Type.__fallbackType && value.fallbackType) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ...this is the only place we we actually assign this...
Type.__fallbackType = value.fallbackType;
}
return Type;
}
+19 -2
View File
@@ -55,11 +55,28 @@ function initType<T extends Codec = Codec, K extends string = string> (registry:
// argument here can be any string, which, when it cannot parse, will yield a
// runtime error.
export function createTypeUnsafe<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K, params: unknown[] = [], options: CreateOptions = {}): T {
let Clazz: Constructor<FromReg<T, K>> | null = null;
let firstError: Error | null = null;
try {
return initType(registry, createClass<T, K>(registry, type), params, options);
Clazz = createClass<T, K>(registry, type);
return initType(registry, Clazz, params, options);
} catch (error) {
throw new Error(`createType(${type}):: ${(error as Error).message}`);
firstError = new Error(`createType(${type}):: ${(error as Error).message}`);
}
if (Clazz && Clazz.__fallbackType) {
try {
Clazz = createClass<T, K>(registry, Clazz.__fallbackType as unknown as K);
return initType(registry, Clazz, params, options);
} catch {
// swallow, we will throw the first error again
}
}
throw firstError;
}
/**
+3 -1
View File
@@ -15,6 +15,7 @@ interface TypeDefOptions {
}
const MAX_NESTED = 64;
const KNOWN_INTERNALS = ['_alias', '_fallback'];
function getTypeString (typeOrObj: any): string {
return isString(typeOrObj)
@@ -100,7 +101,8 @@ function _decodeStruct (value: TypeDef, type: string, _: string, count: number):
value.alias = parsed._alias
? new Map(Object.entries(parsed._alias))
: undefined;
value.sub = keys.filter((name) => !['_alias'].includes(name)).map((name): TypeDef =>
value.fallbackType = parsed._fallback as string | undefined;
value.sub = keys.filter((name) => !KNOWN_INTERNALS.includes(name)).map((name): TypeDef =>
getTypeDef(getTypeString(parsed[name]), { name }, count)
);
+2 -1
View File
@@ -32,9 +32,10 @@ export enum TypeDefInfo {
export interface TypeDef {
alias?: Map<string, string>;
displayName?: string;
fallbackType?: string;
info: TypeDefInfo;
index?: number;
displayName?: string;
length?: number;
name?: string;
namespace?: string;
@@ -140,12 +140,19 @@ export default {
},
types: {
AccountInfo: 'AccountInfoWithTripleRefCount',
AccountInfoWithRefCountU8: {
nonce: 'Index',
refcount: 'u8',
data: 'AccountData'
},
AccountInfoWithRefCount: {
_fallback: 'AccountInfoWithRefCountU8',
nonce: 'Index',
refcount: 'RefCount',
data: 'AccountData'
},
AccountInfoWithDualRefCount: {
_fallback: 'AccountInfoWithRefCount',
nonce: 'Index',
consumers: 'RefCount',
providers: 'RefCount',
@@ -154,6 +161,7 @@ export default {
// original naming
AccountInfoWithProviders: 'AccountInfoWithDualRefCount',
AccountInfoWithTripleRefCount: {
_fallback: 'AccountInfoWithDualRefCount',
nonce: 'Index',
consumers: 'RefCount',
providers: 'RefCount',
+5
View File
@@ -108,6 +108,11 @@ export type CodecArg = Codec | BigInt | BN | boolean | string | Uint8Array | boo
interface CodecArgArray extends Array<CodecArg> {}
export interface Constructor<T = Codec> {
/**
* @description An internal fallback type (previous generation) if encoding fails
*/
readonly __fallbackType?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
new(registry: Registry, ...value: any[]): T;
}
+6 -1
View File
@@ -7,7 +7,12 @@ export type DefinitionTypeEnum = { _enum: DefinitionTypeType[] } | { _enum: Reco
export type DefinitionTypeSet = { _set: Record<string, number> };
export type DefinitionTypeStruct = Record<string, DefinitionTypeType> | { _alias?: Record<string, DefinitionTypeType> } & Record<string, unknown>;
type DefinitionTypeStructExtra = {
_alias?: Record<string, DefinitionTypeType>;
_fallback?: DefinitionTypeType;
} & Record<string, unknown>;
export type DefinitionTypeStruct = Record<string, DefinitionTypeType> | DefinitionTypeStructExtra;
export type DefinitionType = string | DefinitionTypeEnum | DefinitionTypeSet | DefinitionTypeStruct;