Add .eq to Codec (#622)

* Add .eq to Codec

* Tests for Codec .eq

* Extra ()'s around checks

* Update AbstractInt.ts

* Use .size in Map compare

* Equivalency comment

* Update Compact.eq to user wrapper eq
This commit is contained in:
Jaco Greeff
2019-01-23 13:29:03 +01:00
committed by GitHub
parent 83a1b975ce
commit 52718d76f7
42 changed files with 646 additions and 9 deletions
+4
View File
@@ -20,6 +20,10 @@ describe('AccountId', () => {
it('is empty by default', () => {
expect(id.isEmpty).toBe(true);
});
it('equals the empty address', () => {
expect(id.eq('5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUppTZ')).toBe(true);
});
});
describe('decoding', () => {
+7
View File
@@ -40,6 +40,13 @@ export default class AccountId extends U8aFixed {
return value;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
return super.eq(AccountId.decodeAccountId(other));
}
/**
* @description Converts the Object to JSON, typically used for RPC transfers
*/
+8
View File
@@ -30,6 +30,14 @@ describe('AccountIndex', () => {
).toEqual('Mwz15xN8');
});
it('compares ss-58 values', () => {
expect(new AccountIndex(256 * 1).eq('25GUyk')).toBe(true);
});
it('compares numbers', () => {
expect(new AccountIndex('25GUyk').eq(256 * 1)).toBe(true);
});
describe('calcLength', () => {
const testLength = (value: number, length: number) =>
expect(AccountIndex.calcLength(value)).toEqual(length);
+13
View File
@@ -86,6 +86,19 @@ export default class AccountIndex extends U32 {
}
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
// shortcut for BN or Number, don't create an object
if (isBn(other) || isNumber(other)) {
return super.eq(other);
}
// convert and compare
return super.eq(new AccountIndex(other));
}
/**
* @description Returns a hex string representation of the value
*/
+13
View File
@@ -13,6 +13,19 @@ describe('Address', () => {
expect(a.toString()).toBe(expected);
});
describe('utility', () => {
it('equals on AccountId', () => {
const addr = '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCt72s';
expect(new Address(addr).eq(addr)).toBe(true);
});
it('equals on AccountIndex', () => {
// see the test below - these are equivalent (with different prefix encoding)
expect(new Address('PrF3').eq('F7ih')).toBe(true);
});
});
describe('decoding', () => {
testDecode(
'Address',
+7
View File
@@ -84,6 +84,13 @@ export default class Address extends Base<AccountId | AccountIndex> {
: this.raw.encodedLength;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
return this.raw.eq(other);
}
/**
* @description Returns a hex string representation of the value
*/
+10
View File
@@ -34,4 +34,14 @@ describe('Bool', () => {
it('correctly encodes length', () => {
expect(new Bool(true).encodedLength).toEqual(1);
});
describe('utils', () => {
it('compares agains a boolean', () => {
expect(new Bool(true).eq(true)).toBe(true);
});
it('compares agains a Bool', () => {
expect(new Bool(false).eq(new Bool(false))).toBe(true);
});
});
});
+11
View File
@@ -36,6 +36,17 @@ export default class Bool extends Boolean implements Codec {
return 1;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
return this.valueOf() === (
other instanceof Boolean
? other.valueOf()
: other
);
}
/**
* @description Returns a hex string representation of the value
*/
@@ -19,4 +19,13 @@ describe('ChainProperties', () => {
}).entries()]
).toEqual([['decimals', 15], ['tokenSymbol', 'BBQ']]);
});
it('checks equality', () => {
expect(
new ChainProperties({
decimals: 15,
tokenSymbol: 'BBQ'
}).eq([['tokenSymbol', 'BBQ'], ['decimals', 15]])
).toBe(true);
});
});
+8
View File
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec } from './types';
import { compareMap } from './codec/utils';
// TODO Expose known properties as they become known, currently we have `tokenSymbol` (e.g. BBQ)
@@ -38,6 +39,13 @@ export default class ChainProperties extends Map<string, any> implements Codec {
return super.get(name);
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
return compareMap(this, other);
}
/**
* @description Unimplemented, will throw
*/
+10
View File
@@ -42,4 +42,14 @@ describe('Moment', () => {
).toBe(true);
});
});
describe('utils', () => {
it('compares values', () => {
expect(new Moment(123).eq(123)).toBe(true);
});
it('compares values (non-match)', () => {
expect(new Moment(123).eq(456)).toBe(false);
});
});
});
+7
View File
@@ -52,6 +52,13 @@ export default class Moment extends Date implements Codec {
return BITLENGTH / 8;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
return Moment.decodeMoment(other).getTime() === this.getTime();
}
/**
* @description Returns the number of bits in the value
*/
+19
View File
@@ -0,0 +1,19 @@
// 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 Null from './Null';
describe('Null', () => {
it('compares against null', () => {
expect(new Null().eq(null)).toBe(true);
});
it('compares against Null', () => {
expect(new Null().eq(new Null())).toBe(true);
});
it('compares against other (failed)', () => {
expect(new Null().eq()).toBe(false);
});
});
+8
View File
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec } from './types';
import { isNull } from '@polkadot/util';
/**
* @name Null
@@ -17,6 +18,13 @@ export default class Null implements Codec {
return 0;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
return other instanceof Null || isNull(other);
}
/**
* @description Returns a hex string representation of the value
*/
+14
View File
@@ -30,4 +30,18 @@ describe('Text', () => {
testEncode('toString', 'foo');
testEncode('toU8a', Uint8Array.from([12, 102, 111, 111]));
});
describe('utils', () => {
it('compares actual string values', () => {
expect(new Text('123').eq('123')).toBe(true);
});
it('compares actual String values', () => {
expect(new Text('XYX').eq(new String('XYX'))).toBe(true);
});
it('compares actual non-string values (fails)', () => {
expect(new Text('123').eq(123)).toBe(false);
});
});
});
+9
View File
@@ -56,6 +56,15 @@ export default class Text extends String implements Codec {
return super.length;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
return isString(other)
? this.toString() === other.toString()
: false;
}
/**
* @description Returns a hex string representation of the value
*/
+15
View File
@@ -21,6 +21,7 @@ export const DEFAULT_UINT_BITS = 64;
export default abstract class AbstractInt extends BN implements Codec {
protected _bitLength: UIntBitLength;
private _isHexJson: boolean;
private _isNegative: boolean;
constructor (
isNegative: boolean,
@@ -32,6 +33,7 @@ export default abstract class AbstractInt extends BN implements Codec {
this._bitLength = bitLength;
this._isHexJson = isHexJson;
this._isNegative = isNegative;
}
static decodeAbstracInt (value: AnyNumber, bitLength: UIntBitLength, isNegative: boolean): string {
@@ -70,6 +72,19 @@ export default abstract class AbstractInt extends BN implements Codec {
return this._bitLength;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
// Here we are actually overriding the built-in .eq to take care of both
// number and BN inputs (no `.eqn` needed) - numbers will be converted
return super.eq(
isHex(other)
? hexToBn(other.toString(), { isLe: false, isNegative: this._isNegative })
: bnToBn(other)
);
}
/**
* @description Returns the BN representation of the number. (Compatibility)
*/
+10
View File
@@ -137,6 +137,16 @@ describe('Compact', () => {
});
});
describe('utils', () => {
it('compares against another Compact', () => {
expect(new Compact(U32, 12345).eq(new Compact(U32, 12345))).toBe(true);
});
it('compares against a primitive', () => {
expect(new Compact(U32, 12345).eq(12345)).toBe(true);
});
});
describe('helpers', () => {
it('correctly adds the length prefix', () => {
expect(
+11
View File
@@ -80,6 +80,17 @@ export default class Compact extends Base<UInt | Moment> implements Codec {
return this.raw.bitLength();
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
return this.raw.eq(
other instanceof Compact
? other.raw
: other
);
}
/**
* @description Returns the BN representation of the number
*/
+26
View File
@@ -53,4 +53,30 @@ describe('Enum', () => {
new Enum(['foo', 'bar'], 5).toString()
).toEqual('5');
});
describe('utils', () => {
it('compares agains the index value', () => {
expect(
new Enum(['foo', 'bar'], 1).eq(1)
).toBe(true);
});
it('compares agains the index value (false)', () => {
expect(
new Enum(['foo', 'bar'], 1).eq(0)
).toBe(false);
});
it('compares agains the string value', () => {
expect(
new Enum(['foo', 'bar'], 1).eq('bar')
).toBe(true);
});
it('compares agains the string value (false)', () => {
expect(
new Enum(['foo', 'bar'], 1).eq('foo')
).toBe(false);
});
});
});
+13
View File
@@ -65,6 +65,19 @@ export default class Enum extends Base<number> implements Codec {
return 1;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
if (other instanceof Enum) {
return this.raw === other.raw;
}
return isString(other)
? this.toString() === other
: this.raw === other;
}
/**
* @description Returns a hex string representation of the value
*/
+19
View File
@@ -84,4 +84,23 @@ describe('Struct', () => {
expect(enumType.type).toBe('Text');
expect(enumType.value).toEqual(text);
});
describe('utils', () => {
const eqtest = new EnumType(
{ U32, Text },
new Uint8Array([1, 3 << 2, 88, 89, 90])
);
it('compares against index', () => {
expect(
eqtest.eq(1)
).toBe(true);
});
it('compares against values', () => {
expect(
eqtest.eq('XYZ')
).toBe(true);
});
});
});
+13
View File
@@ -130,6 +130,19 @@ export default class EnumType<T> extends Base<Codec> implements Codec {
return this.raw;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
// cater for the case where we only pass the enum index
if (isNumber(other)) {
return this.toNumber() === other;
}
// compare the actual wrapper value
return this.value.eq(other);
}
/**
* @description Returns a hex string representation of the value
*/
@@ -5,7 +5,7 @@
import Option from './Option';
import Text from '../Text';
const testDecode = (type, input, expected) =>
const testDecode = (type: string, input: any, expected: any) =>
it(`can decode from ${type}`, () => {
const o = new Option(Text, input);
@@ -13,11 +13,11 @@ const testDecode = (type, input, expected) =>
expect(o.isNone).toBe(!expected.length);
});
const testEncode = (to, expected) =>
const testEncode = (to: string, expected: any) =>
it(`can encode ${to}`, () => {
const e = new Option(Text, 'foo');
expect(e[to]()).toEqual(expected);
expect((e as any)[to]()).toEqual(expected);
});
describe('Option', () => {
@@ -36,7 +36,7 @@ describe('Option', () => {
testDecode('string (with)', 'foo', 'foo');
testDecode('string (without)', undefined, '');
testDecode('Uint8Array (with)', Uint8Array.from([1, 12, 102, 111, 111]), 'foo');
testDecode('Uint8Array (without)', Uint8Array.from([0]), '', false);
testDecode('Uint8Array (without)', Uint8Array.from([0]), '');
testEncode('toHex', '0x010c666f6f');
testEncode('toString', 'foo');
@@ -65,4 +65,16 @@ describe('Option', () => {
new Option(Text).toU8a()
).toEqual(new Uint8Array([0]));
});
describe('utils', () => {
const testeq = new Option(Text, '1234');
it('compares against other option', () => {
expect(testeq.eq(new Option(Text, '1234'))).toBe(true);
});
it('compares against raw value', () => {
expect(testeq.eq('1234')).toBe(true);
});
});
});
+11
View File
@@ -75,6 +75,17 @@ export default class Option<T extends Codec> extends Base<T> implements Codec {
return this.raw;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
if (other instanceof Option) {
return (this.isSome === other.isSome) && this.value.eq(other.value);
}
return this.value.eq(other);
}
/**
* @description Returns a hex string representation of the value
*/
+28
View File
@@ -42,4 +42,32 @@ describe('Set', () => {
expect(set.toU8a()).toEqual(new Uint8Array([19]));
});
describe('utils', () => {
const set = new Set(SET_ROLES, ['full', 'authority']);
it('compares against string array', () => {
expect(
set.eq(['authority', 'full'])
).toBe(true);
});
it('compares against number (encoded)', () => {
expect(
set.eq(SET_ROLES.full | SET_ROLES.authority)
).toBe(true);
});
it('compares against other sets', () => {
expect(
set.eq(new Set(SET_ROLES, ['authority', 'full']))
).toBe(true);
});
it('returns false on other values', () => {
expect(
set.eq('full')
).toBe(false);
});
});
});
+18 -1
View File
@@ -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, isUndefined, u8aToHex } from '@polkadot/util';
import { isU8a, isNumber, isUndefined, u8aToHex } from '@polkadot/util';
import Base from './Base';
import { Codec } from '../types';
import { compareArray } from './utils';
type SetValues = {
[index: string]: number
@@ -94,6 +95,22 @@ export default class Set extends Base<Array<string>> implements Codec {
return Set.encodeSet(this._setValues, this.raw);
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
if (Array.isArray(other)) {
// we don't actually care about the order, sort the values
return compareArray(this.values.sort(), other.sort());
} else if (other instanceof Set) {
return this.eq(other.values);
} else if (isNumber(other)) {
return this.valueEncoded === other;
}
return false;
}
/**
* @description Returns a hex string representation of the value
*/
+18
View File
@@ -154,4 +154,22 @@ describe('Struct', () => {
.toString()
).toEqual('1234');
});
describe('utils', () => {
it('compares against other objects', () => {
const test = {
foo: 'foo',
bar: 'bar',
baz: 3
};
expect(
new Struct({
foo: Text,
bar: Text,
baz: U32
}, test).eq(test)
).toBe(true);
});
});
});
+8 -1
View File
@@ -5,7 +5,7 @@
import { hexToU8a, isHex, isObject, isU8a, u8aConcat, u8aToHex } from '@polkadot/util';
import { Codec, Constructor, ConstructorDef } from '../types';
import decodeU8a from './utils/decodeU8a';
import { compareMap, decodeU8a } from './utils';
/**
* @name Struct
@@ -152,6 +152,13 @@ export default class Struct<
}, 0);
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
return compareMap(this, other);
}
/**
* @description Returns a specific names entry in the structure
* @param name The name of the entry to retrieve
+9
View File
@@ -85,4 +85,13 @@ describe('Tuple', () => {
expect(tuple.map(v => v.toString())).toEqual(['bazzing', '69']);
});
describe('utils', () => {
it('compares against inputs', () => {
expect(tuple.eq(['bazzing', 69])).toBe(true);
});
it('compares against inputs (mismatch)', () => {
expect(tuple.eq(['bazzing', 72])).toBe(false);
});
});
});
+8 -1
View File
@@ -5,7 +5,7 @@
import { isU8a, u8aConcat, u8aToHex, isHex, hexToU8a } from '@polkadot/util';
import { AnyNumber, AnyU8a, AnyString, Codec, Constructor } from '../types';
import decodeU8a from './utils/decodeU8a';
import { compareArray, decodeU8a } from './utils';
type TupleConstructors = Array<Constructor> | {
[index: string]: Constructor
@@ -71,6 +71,13 @@ export default class Tuple extends Array<Codec> 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
*/
+18
View File
@@ -51,4 +51,22 @@ describe('U8a', () => {
it('implements subarray correctly', () => {
expect(u8a.subarray(1, 3)).toEqual(Uint8Array.from([2, 3]));
});
describe('utils', () => {
it('compares against other U8a', () => {
expect(u8a.eq(new Uint8Array([1, 2, 3, 4, 5]))).toBe(true);
});
it('compares against other U8a (non-length)', () => {
expect(u8a.eq(new Uint8Array([1, 2, 3, 4]))).toBe(false);
});
it('compares against other U8a (mismatch)', () => {
expect(u8a.eq(new Uint8Array([1, 2, 3, 4, 6]))).toBe(false);
});
it('compares against hex inputs', () => {
expect(u8a.eq('0x0102030405')).toBe(true);
});
});
});
+13
View File
@@ -52,6 +52,19 @@ export default class U8a extends Uint8Array implements Codec {
return super.length;
}
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean {
if (other instanceof Uint8Array) {
return (this.length === other.length) && isUndefined(
this.find((value, index) => value !== other[index])
);
}
return this.eq(U8a.decodeU8a(other));
}
/**
* @description Create a new subarray from the actual buffer. This is needed for compat reasons since a new Uint8Array gets returned here
* @param begin The position to start at
+18
View File
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import BN from 'bn.js';
import UInt from './UInt';
describe('UInt', () => {
@@ -48,4 +50,20 @@ describe('UInt', () => {
expect(new UInt(0x12, 16).toJSON()).toEqual('0x0012');
expect(new UInt(0x12, 16, false).toJSON()).toEqual(0x12);
});
describe('eq', () => {
const test = new UInt(12345);
it('compares against other BN values', () => {
expect(test.eq(new BN(12345))).toBe(true);
});
it('compares against other number values', () => {
expect(test.eq(12345)).toBe(true);
});
it('compares against hex values', () => {
expect(test.eq('0x3039')).toBe(true);
});
});
});
+12
View File
@@ -116,4 +116,16 @@ describe('Vector', () => {
testEncode('toString', '[1, 23, 345, 4567, 56789]');
testEncode('toU8a', Uint8Array.from([20, 4, 49, 8, 50, 51, 12, 51, 52, 53, 16, 52, 53, 54, 55, 20, 53, 54, 55, 56, 57]));
});
describe('utils', () => {
const vec = new Vector(Text, ['123', '456']);
it('compares against codec types', () => {
expect(vec.eq([new Text('123'), new Text('456')])).toBe(true);
});
it('compares against codec + primitive types', () => {
expect(vec.eq(['123', new Text('456')])).toBe(true);
});
});
});
+9 -2
View File
@@ -6,12 +6,12 @@ import { u8aConcat, u8aToU8a, u8aToHex } from '@polkadot/util';
import Compact from './Compact';
import { Codec, Constructor } from '../types';
import decodeU8a from './utils/decodeU8a';
import { compareArray, decodeU8a } from './utils';
/**
* @name Vector
* @description
* This manages codec arrays. Intrernally it keeps track of the length (as decoded) and allows
* 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
@@ -75,6 +75,13 @@ export default class Vector<
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
*/
@@ -0,0 +1,48 @@
// 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 U32 from '../../U32';
import compareArray from './compareArray';
describe('compareArray', () => {
const a = [new U32(123), new U32(456), new U32(789)];
it('returns false when second param is a non-array', () => {
expect(
compareArray(a, 123)
).toBe(false);
});
it('compares array of codec agains primitive', () => {
expect(
compareArray(a, [123, 456, 789])
).toBe(true);
});
it('compares array of codec agains codec', () => {
expect(
compareArray(a, [new U32(123), new U32(456), new U32(789)])
).toBe(true);
});
it('compares primitive against primitive', () => {
expect(
compareArray(
[123, 456], [123, 456]
)
).toBe(true);
});
it('returns false when lengths are not matching', () => {
expect(
compareArray(a, [123])
).toBe(false);
});
it('returns false when value mismatches', () => {
expect(
compareArray(a, [123, 456, 999])
).toBe(false);
});
});
@@ -0,0 +1,21 @@
// 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 { isFunction, isUndefined } from '@polkadot/util';
// NOTE These are used internally and when comparing objects, expects that
// when the second is an Array<Codec> that the first has to be as well
export default function compareArray (a: Array<any>, b?: any): boolean {
if (Array.isArray(b)) {
return (a.length === b.length) && isUndefined(
a.find((value, index) =>
isFunction(value.eq)
? !value.eq(b[index])
: value !== b[index]
)
);
}
return false;
}
@@ -0,0 +1,81 @@
// 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 U32 from '../../U32';
import compareMap from './compareMap';
describe('compareMap', () => {
const a = new Map<string, Codec>([
['decimals', new U32(15)],
['missing', new U32(10)],
['foobar', new U32(5)]
]);
const b = new Map<string, any>([
['decimals', 15],
['missing', 10],
['foobar', 5]
]);
const c = new Map<string, Codec>([
['decimals', new U32(15)],
['missing', new U32(10)],
['foobar', new U32(5)]
]);
it('compares Map<string, Codec> against Object', () => {
expect(
compareMap(a, {
decimals: 15,
foobar: 5,
missing: 10
})
).toBe(true);
});
it('compares Map<string, any> against entries array', () => {
expect(
compareMap(b, [
['missing', 10], ['decimals', 15], ['foobar', 5]
])
).toBe(true);
});
it('compares between 2 maps', () => {
expect(compareMap(a, b)).toBe(true);
});
it('compares between 2 maps (both codec)', () => {
expect(compareMap(a, c)).toBe(true);
});
it('returns false when second param is a non-map, non-array, non-object', () => {
expect(
compareMap(a, 123)
).toBe(false);
});
it('returns false when second param is a array with non-entries', () => {
expect(
compareMap(a, [123, 456, 789])
).toBe(false);
});
it('returns false when second param is a array with non-entries (only key)', () => {
expect(
compareMap(a, [[123], [456], [789]])
).toBe(false);
});
it('returns false when properties are missing', () => {
expect(
compareMap(a, [['decimals', 15], ['wrong', 10], ['foobar', 5]])
).toBe(false);
});
it('returns false when lengths do not match', () => {
expect(
compareMap(a, [['decimals', 15]])
).toBe(false);
});
});
@@ -0,0 +1,34 @@
// 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 { isFunction, isObject, isUndefined } from '@polkadot/util';
// NOTE These are used internally and when comparing objects, expects that
// when the second is an Map<string, Codec> that the first has to be as well
export default function compareMap (a: Map<any, any>, b?: any): boolean {
if (Array.isArray(b)) {
return (a.size === b.length) && isUndefined(
b.find((entry) => {
if (!Array.isArray(entry) || entry.length !== 2) {
return true;
}
const value = a.get(entry[0]);
return isUndefined(value) || (
// Codec has .eq, use it here
isFunction(value.eq)
? !value.eq(entry[1])
: value !== entry[1]
);
})
);
} else if (b instanceof Map) {
return compareMap(a, [...b.entries()]);
} else if (isObject(b)) {
return compareMap(a, Object.entries(b));
}
return false;
}
+7
View File
@@ -0,0 +1,7 @@
// 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.
export { default as compareArray } from './compareArray';
export { default as compareMap } from './compareMap';
export { default as decodeU8a } from './decodeU8a';
+5
View File
@@ -23,6 +23,11 @@ export interface Codec {
*/
encodedLength: number;
/**
* @description Compares the value of the input to see if there is a match
*/
eq (other?: any): boolean;
/**
* @description Returns a hex string representation of the value
*/