From 6be6b027cb310659f8acc960ba20dfd28ee85fe9 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 25 Feb 2020 16:53:04 +0100 Subject: [PATCH] More private field -> #field adjustments (#1945) * More private field -> #field adjustments * Work-around for set.add failures * Remove FIXME, it is done --- packages/types/src/codec/BTreeMap.ts | 20 ++-- packages/types/src/codec/BTreeSet.ts | 146 ++++++++++++++------------- packages/types/src/codec/Option.ts | 22 ++-- packages/types/src/codec/Set.ts | 34 +++---- packages/types/src/codec/Struct.ts | 25 +++-- 5 files changed, 125 insertions(+), 122 deletions(-) diff --git a/packages/types/src/codec/BTreeMap.ts b/packages/types/src/codec/BTreeMap.ts index 177dd16857..c8048b717d 100644 --- a/packages/types/src/codec/BTreeMap.ts +++ b/packages/types/src/codec/BTreeMap.ts @@ -66,7 +66,10 @@ function decodeBTreeMapFromMap * @param jsonMap * @internal */ -function decodeBTreeMap (registry: Registry, KeyClass: Constructor, ValClass: Constructor, value: Uint8Array | string | Map): Map { +function decodeBTreeMap (registry: Registry, keyType: Constructor | keyof InterfaceTypes, valType: Constructor | keyof InterfaceTypes, value: Uint8Array | string | Map): Map { + const KeyClass = typeToConstructor(registry, keyType); + const ValClass = typeToConstructor(registry, valType); + if (!value) { return new Map(); } else if (isHex(value)) { @@ -83,19 +86,16 @@ function decodeBTreeMap (regis export default class BTreeMap extends Map implements Codec { public readonly registry: Registry; - protected _KeyClass: Constructor; + readonly #KeyClass: Constructor; - protected _ValClass: Constructor; + readonly #ValClass: Constructor; constructor (registry: Registry, keyType: Constructor | keyof InterfaceTypes, valType: Constructor | keyof InterfaceTypes, rawValue: any) { - const KeyClass = typeToConstructor(registry, keyType); - const ValClass = typeToConstructor(registry, valType); - - super(decodeBTreeMap(registry, KeyClass, ValClass, rawValue)); + super(decodeBTreeMap(registry, keyType, valType, rawValue)); this.registry = registry; - this._KeyClass = KeyClass; - this._ValClass = ValClass; + this.#KeyClass = typeToConstructor(registry, keyType); + this.#ValClass = typeToConstructor(registry, valType); } public static with (keyType: Constructor | keyof InterfaceTypes, valType: Constructor | keyof InterfaceTypes): Constructor> { @@ -177,7 +177,7 @@ export default class BTreeMap * @description Returns the base runtime type name for this instance */ public toRawType (): string { - return `BTreeMap<${new this._KeyClass(this.registry).toRawType()},${new this._ValClass(this.registry).toRawType()}>`; + return `BTreeMap<${new this.#KeyClass(this.registry).toRawType()},${new this.#ValClass(this.registry).toRawType()}>`; } /** diff --git a/packages/types/src/codec/BTreeSet.ts b/packages/types/src/codec/BTreeSet.ts index 5ea24d277d..90b10df6d4 100644 --- a/packages/types/src/codec/BTreeSet.ts +++ b/packages/types/src/codec/BTreeSet.ts @@ -12,84 +12,86 @@ import Compact from './Compact'; import Raw from './Raw'; import { compareSet, decodeU8a, typeToConstructor } from './utils'; +/** @internal */ +function decodeBTreeSetFromU8a (registry: Registry, ValClass: Constructor, u8a: Uint8Array): Set { + const output = new Set(); + const [offset, length] = Compact.decodeU8a(u8a); + const types = []; + + for (let i = 0; i < length.toNumber(); i++) { + types.push(ValClass); + } + + const values = decodeU8a(registry, u8a.subarray(offset), types); + + for (let i = 0; i < values.length; i++) { + output.add(values[i] as V); + } + + return output; +} + +/** @internal */ +function decodeBTreeSetFromSet (registry: Registry, ValClass: Constructor, value: Set): Set { + const output = new Set(); + + value.forEach((v: any) => { + let val; + try { + val = (v instanceof ValClass) ? v : new ValClass(registry, v); + } catch (error) { + console.error('Failed to decode BTreeSet key or value:', error.message); + throw error; + } + + output.add(val); + }); + + return output; +} + +/** + * Decode input to pass into constructor. + * + * @param ValClass - Type of the map value + * @param value - Value to decode, one of: + * - null + * - undefined + * - hex + * - Uint8Array + * - Set, where both key and value types are either + * constructors or decodeable values for their types. + * @param jsonSet + * @internal + */ +function decodeBTreeSet (registry: Registry, valType: Constructor | keyof InterfaceTypes, value: Uint8Array | string | Set): Set { + if (!value) { + return new Set(); + } + + const ValClass = typeToConstructor(registry, valType); + + if (isHex(value)) { + return decodeBTreeSet(registry, ValClass, hexToU8a(value)); + } else if (isU8a(value)) { + return decodeBTreeSetFromU8a(registry, ValClass, u8aToU8a(value)); + } else if (value instanceof Set) { + return decodeBTreeSetFromSet(registry, ValClass, value); + } + + throw new Error('BTreeSet: cannot decode type'); +} + export default class BTreeSet extends Set implements Codec { public readonly registry: Registry; - private readonly _ValClass: Constructor; + readonly #ValClass: Constructor; constructor (registry: Registry, valType: Constructor | keyof InterfaceTypes, rawValue: any) { - const ValClass = typeToConstructor(registry, valType); - - super(BTreeSet.decodeBTreeSet(registry, ValClass, rawValue)); + super(decodeBTreeSet(registry, valType, rawValue)); this.registry = registry; - this._ValClass = ValClass; - } - - /** - * Decode input to pass into constructor. - * - * @param ValClass - Type of the map value - * @param value - Value to decode, one of: - * - null - * - undefined - * - hex - * - Uint8Array - * - Set, where both key and value types are either - * constructors or decodeable values for their types. - * @param jsonSet - * @internal - */ - private static decodeBTreeSet (registry: Registry, ValClass: Constructor, value: Uint8Array | string | Set): Set { - if (!value) { - return new Set(); - } else if (isHex(value)) { - return BTreeSet.decodeBTreeSet(registry, ValClass, hexToU8a(value)); - } else if (isU8a(value)) { - return BTreeSet.decodeBTreeSetFromU8a(registry, ValClass, u8aToU8a(value)); - } else if (value instanceof Set) { - return BTreeSet.decodeBTreeSetFromSet(registry, ValClass, value); - } - - throw new Error('BTreeSet: cannot decode type'); - } - - /** @internal */ - private static decodeBTreeSetFromU8a (registry: Registry, ValClass: Constructor, u8a: Uint8Array): Set { - const output = new Set(); - const [offset, length] = Compact.decodeU8a(u8a); - const types = []; - - for (let i = 0; i < length.toNumber(); i++) { - types.push(ValClass); - } - - const values = decodeU8a(registry, u8a.subarray(offset), types); - - for (let i = 0; i < values.length; i++) { - output.add(values[i] as V); - } - - return output; - } - - /** @internal */ - private static decodeBTreeSetFromSet (registry: Registry, ValClass: Constructor, value: Set): Set { - const output = new Set(); - - value.forEach((v: any) => { - let val; - try { - val = (v instanceof ValClass) ? v : new ValClass(registry, v); - } catch (error) { - console.error('Failed to decode BTreeSet key or value:', error.message); - throw error; - } - - output.add(val); - }); - - return output; + this.#ValClass = typeToConstructor(registry, valType); } public static with (valType: Constructor | keyof InterfaceTypes): Constructor> { @@ -171,7 +173,7 @@ export default class BTreeSet extends Set implements * @description Returns the base runtime type name for this instance */ public toRawType (): string { - return `BTreeSet<${new this._ValClass(this.registry).toRawType()}>`; + return `BTreeSet<${new this.#ValClass(this.registry).toRawType()}>`; } /** diff --git a/packages/types/src/codec/Option.ts b/packages/types/src/codec/Option.ts index da3e918475..5674e3d029 100644 --- a/packages/types/src/codec/Option.ts +++ b/packages/types/src/codec/Option.ts @@ -18,11 +18,15 @@ function decodeOptionU8a (registry: Registry, Type: Constructor, value: Uint8Arr } /** @internal */ -function decodeOption (registry: Registry, Type: Constructor, value?: any): Codec { +function decodeOption (registry: Registry, typeName: Constructor | keyof InterfaceTypes, value?: any): Codec { if (isNull(value) || isUndefined(value) || value instanceof Null) { return new Null(registry); + } + + const Type = typeToConstructor(registry, typeName); + // eslint-disable-next-line @typescript-eslint/no-use-before-define - } else if (value instanceof Option) { + if (value instanceof Option) { return decodeOption(registry, Type, value.value); } else if (value instanceof Type) { // don't re-create, use as it (which also caters for derived types) @@ -45,14 +49,12 @@ function decodeOption (registry: Registry, Type: Constructor, value?: any): Code * with a value if/as required/found. */ export default class Option extends Base { - private _Type: Constructor; + readonly #Type: Constructor; - constructor (registry: Registry, Type: Constructor | keyof InterfaceTypes, value?: any) { - const Clazz = typeToConstructor(registry, Type); + constructor (registry: Registry, typeName: Constructor | keyof InterfaceTypes, value?: any) { + super(registry, decodeOption(registry, typeName, value)); - super(registry, decodeOption(registry, Clazz, value)); - - this._Type = Clazz; + this.#Type = typeToConstructor(registry, typeName); } public static with (Type: Constructor | keyof InterfaceTypes): Constructor> { @@ -125,7 +127,7 @@ export default class Option extends Base { * @description Returns the base runtime type name for this instance */ public toRawType (isBare?: boolean): string { - const wrapped = new this._Type(this.registry).toRawType(); + const wrapped = new this.#Type(this.registry).toRawType(); return isBare ? wrapped @@ -179,6 +181,6 @@ export default class Option extends Base { public unwrapOrDefault (): T { return this.isSome ? this.unwrap() - : new this._Type(this.registry); + : new this.#Type(this.registry); } } diff --git a/packages/types/src/codec/Set.ts b/packages/types/src/codec/Set.ts index af0a939516..2a29e8abf8 100644 --- a/packages/types/src/codec/Set.ts +++ b/packages/types/src/codec/Set.ts @@ -50,7 +50,11 @@ function decodeSetNumber (setValues: SetValues, _value: BN | number): string[] { } /** @internal */ -function decodeSet (setValues: SetValues, value: string[] | Set | Uint8Array | BN | number | string = 0, byteLength: number): string[] { +function decodeSet (setValues: SetValues, value: string[] | Set | Uint8Array | BN | number | string = 0, bitLength: number): string[] { + assert(bitLength % 8 === 0, `Expected valid bitLength, power of 8, found ${bitLength}`); + + const byteLength = bitLength / 8; + if (isString(value)) { return decodeSet(setValues, u8aToU8a(value), byteLength); } else if (isU8a(value)) { @@ -78,20 +82,16 @@ function decodeSet (setValues: SetValues, value: string[] | Set | Uint8A export default class CodecSet extends Set implements Codec { public readonly registry: Registry; - protected _byteLength: number; + readonly #allowed: SetValues; - protected _setValues: SetValues; + readonly #byteLength: number; constructor (registry: Registry, setValues: SetValues, value?: string[] | Set | Uint8Array | BN | number | string, bitLength = 8) { - assert(bitLength % 8 === 0, `Expected valid bitLength, power of 8, found ${bitLength}`); - - const byteLength = bitLength / 8; - - super(decodeSet(setValues, value, byteLength)); + super(decodeSet(setValues, value, bitLength)); this.registry = registry; - this._byteLength = byteLength; - this._setValues = setValues; + this.#allowed = setValues; + this.#byteLength = bitLength / 8; } public static with (values: SetValues, bitLength?: number): Constructor { @@ -119,7 +119,7 @@ export default class CodecSet extends Set implements Codec { * @description The length of the value when encoded as a Uint8Array */ public get encodedLength (): number { - return this._byteLength; + return this.#byteLength; } /** @@ -147,16 +147,17 @@ export default class CodecSet extends Set implements Codec { * @description The encoded value for the set members */ public get valueEncoded (): BN { - return encodeSet(this._setValues, this.strings); + return encodeSet(this.#allowed, this.strings); } /** * @description adds a value to the Set (extended to allow for validity checking) */ - public add (key: string): this { + public add = (key: string): this => { + // ^^^ add = () property done to assign this instance's this, otherwise Set.add creates "some" chaos // we have the isUndefined(this._setValues) in here as well, add is used internally // in the Set constructor (so it is undefined at this point, and should allow) - assert(isUndefined(this._setValues) || !isUndefined(this._setValues[key]), `Set: Invalid key '${key}' on add`); + assert(isUndefined(this.#allowed) || !isUndefined(this.#allowed[key]), `Set: Invalid key '${key}' on add`); super.add(key); @@ -211,8 +212,7 @@ export default class CodecSet extends Set implements Codec { * @description Returns the base runtime type name for this instance */ public toRawType (): string { - // FIXME We don't cater for this in createType as of yet - return JSON.stringify({ _set: this._setValues }); + return JSON.stringify({ _set: this.#allowed }); } /** @@ -228,6 +228,6 @@ export default class CodecSet extends Set implements Codec { */ // eslint-disable-next-line @typescript-eslint/no-unused-vars public toU8a (isBare?: boolean): Uint8Array { - return bnToU8a(this.valueEncoded, { isLe: false, bitLength: this._byteLength * 8 }); + return bnToU8a(this.valueEncoded, { isLe: false, bitLength: this.#byteLength * 8 }); } } diff --git a/packages/types/src/codec/Struct.ts b/packages/types/src/codec/Struct.ts index 6ba605d59f..7e8e7d366e 100644 --- a/packages/types/src/codec/Struct.ts +++ b/packages/types/src/codec/Struct.ts @@ -105,19 +105,18 @@ export default class Struct< E extends { [K in keyof S]: string } = { [K in keyof S]: string }> extends Map implements Codec { public readonly registry: Registry; - protected _jsonMap: Map; + readonly #jsonMap: Map; - protected _Types: ConstructorDef; + readonly #Types: ConstructorDef; constructor (registry: Registry, Types: S, value: V | Map | any[] | string = {} as V, jsonMap: Map = new Map()) { - const Clazzes = mapToTypeMap(registry, Types); - const decoded: T = decodeStruct(registry, Clazzes, value, jsonMap); - - super(Object.entries(decoded)); + super(Object.entries( + decodeStruct(registry, mapToTypeMap(registry, Types), value, jsonMap) + ) as [keyof S, Codec][]); this.registry = registry; - this._jsonMap = jsonMap; - this._Types = Clazzes; + this.#jsonMap = jsonMap; + this.#Types = mapToTypeMap(registry, Types); } public static with (Types: S): Constructor> { @@ -144,7 +143,7 @@ export default class Struct< * @description The available keys for this enum */ public get defKeys (): string[] { - return Object.keys(this._Types); + return Object.keys(this.#Types); } /** @@ -167,7 +166,7 @@ export default class Struct< */ public get Type (): E { return (Object - .entries(this._Types) as [keyof S, Constructor][]) + .entries(this.#Types) as [keyof S, Constructor][]) .reduce((result: E, [key, Type]): E => { (result as any)[key] = new Type(this.registry).toRawType(); @@ -234,7 +233,7 @@ export default class Struct< */ public toHuman (isExtended?: boolean): AnyJson { return [...this.keys()].reduce((json, key): any => { - const jsonKey = this._jsonMap.get(key) || key; + const jsonKey = this.#jsonMap.get(key) || key; const value = this.get(key); json[jsonKey] = value && value.toHuman(isExtended); @@ -250,7 +249,7 @@ export default class Struct< // FIXME the return type string is only used by Extrinsic (extends Struct), // but its toJSON is the hex value return [...this.keys()].reduce((json, key): any => { - const jsonKey = this._jsonMap.get(key) || key; + const jsonKey = this.#jsonMap.get(key) || key; const value = this.get(key); json[jsonKey] = value && value.toJSON(); @@ -272,7 +271,7 @@ export default class Struct< */ public toRawType (): string { return JSON.stringify( - Struct.typesToMap(this.registry, this._Types) + Struct.typesToMap(this.registry, this.#Types) ); }