codec/Set extends JS Set (#917)
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
# 0.79.1
|
||||
|
||||
- Support latest EventRecord metadata (substrate master)
|
||||
- Introduce RuntimeVeriosion type overrides in api/nodeCompat.ts
|
||||
- Add `api.queryMulti` and `api.query.<module>.<method>.multi`
|
||||
- Convert `api.derive.*` to use multi queries
|
||||
- `types/codec/Set` now extends the base JS `Set` (breaking: `set.values` -> `set.strings`)
|
||||
|
||||
# 0.78.1
|
||||
|
||||
- Fix linked-maps (not working since 0.77.1)
|
||||
|
||||
@@ -20,7 +20,7 @@ const SET_ROLES = {
|
||||
|
||||
describe('Set', () => {
|
||||
it('constructs via an Array<string>', () => {
|
||||
const set = new Set(SET_ROLES, ['full', 'authority', 'invalid']);
|
||||
const set = new Set(SET_ROLES, ['full', 'authority']);
|
||||
|
||||
expect(set.isEmpty).toEqual(false);
|
||||
expect(set.toString()).toEqual(
|
||||
@@ -28,6 +28,18 @@ describe('Set', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('throws with invalid values', () => {
|
||||
expect(
|
||||
() => new Set(SET_ROLES, ['full', 'authority', 'invalid'])
|
||||
).toThrow(/Invalid key 'invalid'/);
|
||||
});
|
||||
|
||||
it('throws with add on invalid', () => {
|
||||
expect(
|
||||
() => (new Set(SET_ROLES, [])).add('invalid')
|
||||
).toThrow(/Invalid key 'invalid'/);
|
||||
});
|
||||
|
||||
it('constructs via Uint8Array', () => {
|
||||
const set = new Set(SET_FIELDS, new Uint8Array([0b00000001 | 0b00000010 | 0b00010000 | 0b10000000]));
|
||||
|
||||
|
||||
@@ -2,9 +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 { isU8a, isNumber, isUndefined, u8aToHex } from '@plugnet/util';
|
||||
import { assert, isU8a, isNumber, isUndefined, u8aToHex } from '@plugnet/util';
|
||||
|
||||
import Base from './Base';
|
||||
import { Codec } from '../types';
|
||||
import { compareArray } from './utils';
|
||||
|
||||
@@ -19,27 +18,29 @@ type SetValues = {
|
||||
* a bitwise representation of the values.
|
||||
*/
|
||||
// FIXME This is a prime candidate to extend the JavaScript built-in Set
|
||||
export default class Set extends Base<Array<string>> implements Codec {
|
||||
export default class CodecSet extends Set<string> implements Codec {
|
||||
private _setValues: SetValues;
|
||||
|
||||
constructor (setValues: SetValues, value?: Array<string> | Uint8Array | number) {
|
||||
constructor (setValues: SetValues, value?: Array<string> | Set<string> | Uint8Array | number) {
|
||||
super(
|
||||
Set.decodeSet(setValues, value)
|
||||
CodecSet.decodeSet(setValues, value)
|
||||
);
|
||||
|
||||
this._setValues = setValues;
|
||||
}
|
||||
|
||||
static decodeSet (setValues: SetValues, value: Array<string> | Uint8Array | number = 0): Array<string> {
|
||||
static decodeSet (setValues: SetValues, value: Array<string> | Set<string> | Uint8Array | number = 0): Array<string> {
|
||||
if (isU8a(value)) {
|
||||
return Set.decodeSet(setValues, value[0]);
|
||||
return value.length === 0
|
||||
? []
|
||||
: CodecSet.decodeSet(setValues, value[0]);
|
||||
} else if (value instanceof Set) {
|
||||
return CodecSet.decodeSet(setValues, [...value.values()]);
|
||||
} else if (Array.isArray(value)) {
|
||||
return value.reduce((result, value) => {
|
||||
if (isUndefined(setValues[value])) {
|
||||
console.error(`Ignoring invalid '${value}' passed to Set`);
|
||||
} else {
|
||||
result.push(value);
|
||||
}
|
||||
return value.reduce((result, key) => {
|
||||
assert(!isUndefined(setValues[key]), `Set: Invalid key '${key}' passed to Set, allowed ${Object.keys(setValues).join(', ')}`);
|
||||
|
||||
result.push(key);
|
||||
|
||||
return result;
|
||||
}, [] as Array<string>);
|
||||
@@ -52,11 +53,10 @@ export default class Set extends Base<Array<string>> implements Codec {
|
||||
|
||||
return result;
|
||||
}, [] as Array<string>);
|
||||
const computed = Set.encodeSet(setValues, result);
|
||||
|
||||
if (value !== computed) {
|
||||
console.error(`Mismatch decoding '${value}', computed as '${computed}' with ${result}`);
|
||||
}
|
||||
const computed = CodecSet.encodeSet(setValues, result);
|
||||
|
||||
assert(value !== computed, `Set: Mismatch decoding '${value}', computed as '${computed}' with ${result}`);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -78,21 +78,34 @@ export default class Set extends Base<Array<string>> implements Codec {
|
||||
* @description true is the Set contains no values
|
||||
*/
|
||||
get isEmpty (): boolean {
|
||||
return this.values.length === 0;
|
||||
return this.size === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The actual set values as a Array<string>
|
||||
*/
|
||||
get values (): Array<string> {
|
||||
return this.raw;
|
||||
get strings (): Array<string> {
|
||||
return [...super.values()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The encoded value for the set members
|
||||
*/
|
||||
get valueEncoded (): number {
|
||||
return Set.encodeSet(this._setValues, this.raw);
|
||||
return CodecSet.encodeSet(this._setValues, this.strings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description adds a value to the Set (extended to allow for validity checking)
|
||||
*/
|
||||
add (key: string): this {
|
||||
// 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`);
|
||||
|
||||
super.add(key);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,9 +114,9 @@ export default class Set extends Base<Array<string>> implements Codec {
|
||||
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());
|
||||
return compareArray(this.strings.sort(), other.sort());
|
||||
} else if (other instanceof Set) {
|
||||
return this.eq(other.values);
|
||||
return this.eq([...other.values()]);
|
||||
} else if (isNumber(other)) {
|
||||
return this.valueEncoded === other;
|
||||
}
|
||||
@@ -122,14 +135,14 @@ export default class Set extends Base<Array<string>> implements Codec {
|
||||
* @description Converts the Object to JSON, typically used for RPC transfers
|
||||
*/
|
||||
toJSON (): any {
|
||||
return this.values;
|
||||
return this.strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the string representation of the value
|
||||
*/
|
||||
toString (): string {
|
||||
return `[${this.values.join(', ')}]`;
|
||||
return `[${this.strings.join(', ')}]`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,27 +23,27 @@ export default class WithdrawReasons extends Set {
|
||||
* @description In order to reserve some funds for a later return or repatriation
|
||||
*/
|
||||
get isReserve (): boolean {
|
||||
return this.values.includes('Reserve');
|
||||
return this.strings.includes('Reserve');
|
||||
}
|
||||
|
||||
/**
|
||||
* @description In order to pay for (system) transaction costs
|
||||
*/
|
||||
get isTransactionPayment (): boolean {
|
||||
return this.values.includes('TransactionPayment');
|
||||
return this.strings.includes('TransactionPayment');
|
||||
}
|
||||
|
||||
/**
|
||||
* @description In order to transfer ownership
|
||||
*/
|
||||
get isTransfer (): boolean {
|
||||
return this.values.includes('Transfer');
|
||||
return this.strings.includes('Transfer');
|
||||
}
|
||||
|
||||
/**
|
||||
* @description /// In order to pay some other (higher-level) fees.
|
||||
*/
|
||||
get isFee (): boolean {
|
||||
return this.values.includes('Fee');
|
||||
return this.strings.includes('Fee');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user