diff --git a/packages/types/src/codec/AbstractArray.ts b/packages/types/src/codec/AbstractArray.ts new file mode 100644 index 0000000000..60c2b94817 --- /dev/null +++ b/packages/types/src/codec/AbstractArray.ts @@ -0,0 +1,123 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { u8aConcat, u8aToHex } from '@polkadot/util'; + +import Compact from './Compact'; +import { Codec } from '../types'; +import { compareArray } from './utils'; + +/** + * @name AbstractArray + * @description + * This manages codec arrays. It is an extension to Array, providing + * specific encoding/decoding on top of the base type. + * @noInheritDoc + */ +export default abstract class AbstractArray extends Array implements Codec { + /** + * @description Checks if the value is an empty value + */ + get isEmpty (): boolean { + return this.length === 0; + } + + /** + * @description The length of the value when encoded as a Uint8Array + */ + get encodedLength (): number { + return this.reduce((total, raw) => { + return total + raw.encodedLength; + }, Compact.encodeU8a(this.length).length); + } + + /** + * @description The length of the value + */ + get length (): number { + // only included here since we ignore inherited docs + return super.length; + } + + /** + * @description Compares the value of the input to see if there is a match + */ + eq (other?: any): boolean { + return compareArray(this, other); + } + + /** + * @description Converts the Object to an standard JavaScript Array + */ + toArray (): Array { + return Array.from(this); + } + + /** + * @description Returns a hex string representation of the value + */ + toHex (): string { + return u8aToHex(this.toU8a()); + } + + /** + * @description Converts the Object to JSON, typically used for RPC transfers + */ + toJSON (): any { + return this.map((entry) => + entry.toJSON() + ); + } + + /** + * @description Returns the string representation of the value + */ + toString (): string { + // Overwrite the default toString representation of Array. + const data = this.map((entry) => + entry.toString() + ); + + return `[${data.join(', ')}]`; + } + + /** + * @description Encodes the value as a Uint8Array as per the parity-codec specifications + * @param isBare true when the value has none of the type-specific prefixes (internal) + */ + toU8a (isBare?: boolean): Uint8Array { + const encoded = this.map((entry) => + entry.toU8a(isBare) + ); + + return isBare + ? u8aConcat(...encoded) + : u8aConcat( + Compact.encodeU8a(this.length), + ...encoded + ); + } + + // 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. + + /** + * @description Filters the array with the callback + * @param callbackfn The filter function + * @param thisArg The `this` object to apply the result to + */ + filter (callbackfn: (value: T, index: number, array: Array) => any, thisArg?: any): Array { + return this.toArray().filter(callbackfn, thisArg); + } + + /** + * @description Maps the array with the callback + * @param callbackfn The mapping function + * @param thisArg The `this` onject to apply the result to + */ + map (callbackfn: (value: T, index: number, array: Array) => U, thisArg?: any): Array { + return this.toArray().map(callbackfn, thisArg); + } +} diff --git a/packages/types/src/codec/Tuple.ts b/packages/types/src/codec/Tuple.ts index 5384a190ae..ccaf8bf980 100644 --- a/packages/types/src/codec/Tuple.ts +++ b/packages/types/src/codec/Tuple.ts @@ -2,10 +2,11 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { isU8a, u8aConcat, u8aToHex, isHex, hexToU8a } from '@polkadot/util'; +import { isU8a, u8aConcat, isHex, hexToU8a } from '@polkadot/util'; import { AnyNumber, AnyU8a, AnyString, Codec, Constructor } from '../types'; -import { compareArray, decodeU8a } from './utils'; +import { decodeU8a } from './utils'; +import AbstractArray from './AbstractArray'; type TupleConstructors = Array | { [index: string]: Constructor @@ -16,9 +17,8 @@ type TupleConstructors = Array | { * @description * A Tuple defines an anonymous fixed-length array, where each element has its * own type. It extends the base JS `Array` object. - * @noInheritDoc */ -export default class Tuple extends Array implements Codec { +export default class Tuple extends AbstractArray { private _Types: TupleConstructors; constructor (Types: TupleConstructors, value: any) { @@ -62,13 +62,6 @@ export default class Tuple extends Array implements Codec { }, 0); } - /** - * @description Checks if the value is an empty value - */ - get isEmpty (): boolean { - return this.length === 0; - } - /** * @description The types definition of the tuple */ @@ -78,36 +71,6 @@ export default class Tuple extends Array implements Codec { : Object.keys(this._Types); } - /** - * @description Compares the value of the input to see if there is a match - */ - eq (other?: any): boolean { - return compareArray(this, other); - } - - /** - * @description Converts the Object to an standard JavaScript Array - */ - toArray (): Array { - return Array.from(this); - } - - /** - * @description Returns a hex string representation of the value - */ - toHex () { - return u8aToHex(this.toU8a()); - } - - /** - * @description Converts the Object to JSON, typically used for RPC transfers - */ - toJSON (): any { - return this.map((entry) => - entry.toJSON() - ); - } - /** * @description Returns the string representation of the value */ @@ -127,26 +90,4 @@ export default class Tuple extends Array implements Codec { ) ); } - - // Below are methods that we override. When we do a `new Tuple(...).map()`, - // we want it to throw an error. We only override the methods that return a - // new instance. - - /** - * @description Filters the array with the callback - * @param callbackfn The filter function - * @param thisArg The `this` object to apply the result to - */ - filter (callbackfn: (value: Codec, index: number, array: Array) => any, thisArg?: any): Array { - return this.toArray().filter(callbackfn, thisArg); - } - - /** - * @description Maps the array with the callback - * @param callbackfn The mapping function - * @param thisArg The `this` onject to apply the result to - */ - map (callbackfn: (value: Codec, index: number, array: Array) => U, thisArg?: any): Array { - return this.toArray().map(callbackfn, thisArg); - } } diff --git a/packages/types/src/codec/Vector.ts b/packages/types/src/codec/Vector.ts index a03f984d9a..a1a38a9341 100644 --- a/packages/types/src/codec/Vector.ts +++ b/packages/types/src/codec/Vector.ts @@ -2,11 +2,12 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { u8aConcat, u8aToU8a, u8aToHex } from '@polkadot/util'; +import { u8aToU8a } from '@polkadot/util'; import Compact from './Compact'; import { Codec, Constructor } from '../types'; -import { compareArray, decodeU8a } from './utils'; +import { decodeU8a } from './utils'; +import AbstractArray from './AbstractArray'; /** * @name Vector @@ -14,11 +15,8 @@ import { compareArray, decodeU8a } from './utils'; * This manages codec arrays. Internally it keeps track of the length (as decoded) and allows * construction with the passed `Type` in the constructor. It is an extension to Array, providing * specific encoding/decoding on top of the base type. - * @noInheritDoc */ -export default class Vector< - T extends Codec - > extends Array implements Codec { +export default class Vector extends AbstractArray { private _Type: Constructor; constructor (Type: Constructor, value: Vector | Uint8Array | string | Array = [] as Array) { @@ -53,13 +51,6 @@ export default class Vector< }; } - /** - * @description Checks if the value is an empty value - */ - get isEmpty (): boolean { - return this.length === 0; - } - /** * @description The type for the items */ @@ -67,30 +58,6 @@ export default class Vector< return this._Type.name; } - /** - * @description The length of the value when encoded as a Uint8Array - */ - get encodedLength (): number { - return this.reduce((total, raw) => { - return total + raw.encodedLength; - }, Compact.encodeU8a(this.length).length); - } - - /** - * @description The length of the value - */ - get length (): number { - // only included here since we ignore inherited docs - return super.length; - } - - /** - * @description Compares the value of the input to see if there is a match - */ - eq (other?: any): boolean { - return compareArray(this, other); - } - /** * @description Finds the index of the value in the array */ @@ -108,78 +75,4 @@ export default class Vector< return -1; } - - /** - * @description Converts the Object to an standard JavaScript Array - */ - toArray (): Array { - return Array.from(this); - } - - /** - * @description Returns a hex string representation of the value - */ - toHex (): string { - return u8aToHex(this.toU8a()); - } - - /** - * @description Converts the Object to JSON, typically used for RPC transfers - */ - toJSON (): any { - return this.map((entry) => - entry.toJSON() - ); - } - - /** - * @description Returns the string representation of the value - */ - toString (): string { - // Overwrite the default toString representation of Array. - const data = this.map((entry) => - entry.toString() - ); - - return `[${data.join(', ')}]`; - } - - /** - * @description Encodes the value as a Uint8Array as per the parity-codec specifications - * @param isBare true when the value has none of the type-specific prefixes (internal) - */ - toU8a (isBare?: boolean): Uint8Array { - const encoded = this.map((entry) => - entry.toU8a(isBare) - ); - - return isBare - ? u8aConcat(...encoded) - : u8aConcat( - Compact.encodeU8a(this.length), - ...encoded - ); - } - - // 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. - - /** - * @description Filters the array with the callback - * @param callbackfn The filter function - * @param thisArg The `this` object to apply the result to - */ - filter (callbackfn: (value: T, index: number, array: Array) => any, thisArg?: any): Array { - return this.toArray().filter(callbackfn, thisArg); - } - - /** - * @description Maps the array with the callback - * @param callbackfn The mapping function - * @param thisArg The `this` onject to apply the result to - */ - map (callbackfn: (value: T, index: number, array: Array) => U, thisArg?: any): Array { - return this.toArray().map(callbackfn, thisArg); - } } diff --git a/packages/types/src/codec/VectorAny.ts b/packages/types/src/codec/VectorAny.ts new file mode 100644 index 0000000000..6fbb4da865 --- /dev/null +++ b/packages/types/src/codec/VectorAny.ts @@ -0,0 +1,16 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { Codec } from '../types'; +import AbstractArray from './AbstractArray'; + +/** + * @name VectorAny + * @description + * This manages codec arrays, assuming that the inputs are already of type Codec. Unlike + * a vector, this cane be used to manage array-like structures with variable arguments of + * any types + */ +export default class VectorAny extends AbstractArray { +}