Add Set basetype (#365)
* Add Set basetype * Test and log invalid init values * Set.value -> Set.values * isEmpty used this.values in Set * Cleanup erronenous export * Export Option for codec
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
import { isNumber, isObject, isU8a, isUndefined, u8aConcat } from '@polkadot/util';
|
||||
|
||||
import Base from './Base';
|
||||
import Null from '../Null';
|
||||
import { Constructor } from '../types';
|
||||
|
||||
type TypesArray = Array<Constructor<Base>>;
|
||||
@@ -79,6 +80,10 @@ export default class EnumType<T> extends Base<Base<T>> {
|
||||
return { index: 0, value: new (Object.values(def)[0])() };
|
||||
}
|
||||
|
||||
get isNull (): boolean {
|
||||
return this.raw instanceof Null;
|
||||
}
|
||||
|
||||
get type (): string {
|
||||
return this._Types[this._index].name;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2017-2018 @polkadot/types authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import Set from './Set';
|
||||
|
||||
describe('Set', () => {
|
||||
it('constructs via an Array<string>', () => {
|
||||
const set = new Set({
|
||||
none: 0b00000000,
|
||||
full: 0b00000001,
|
||||
light: 0b00000010,
|
||||
authority: 0b00000100
|
||||
}, ['full', 'authority', 'invalid']);
|
||||
|
||||
expect(set.isEmpty).toEqual(false);
|
||||
expect(set.toString()).toEqual(
|
||||
'[full, authority]'
|
||||
);
|
||||
});
|
||||
|
||||
it('constructs via Uint8Array', () => {
|
||||
const set = new Set({
|
||||
header: 0b00000001,
|
||||
body: 0b00000010,
|
||||
receipt: 0b00000100,
|
||||
messageQueue: 0b00001000,
|
||||
justification: 0b00010000
|
||||
}, new Uint8Array([0b00000001 | 0b00000010 | 0b00010000 | 0b10000000]));
|
||||
|
||||
expect(set.encodedLength).toEqual(1);
|
||||
expect(set.toJSON()).toEqual([
|
||||
'header', 'body', 'justification'
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright 2017-2018 @polkadot/types authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { isU8a, isUndefined } from '@polkadot/util';
|
||||
|
||||
import Base from './Base';
|
||||
|
||||
type SetValues = {
|
||||
[index: string]: number
|
||||
};
|
||||
|
||||
// An Set is an array of string values, represented an an encoded type by
|
||||
// a bitwise representation of the values.
|
||||
//
|
||||
// FIXME This is a prime candidate to potentially extend Set
|
||||
export default class Set extends Base<Array<string>> {
|
||||
private _setValues: SetValues;
|
||||
|
||||
constructor (setValues: SetValues, value?: Array<string> | Uint8Array | number) {
|
||||
super(
|
||||
Set.decodeSet(setValues, value)
|
||||
);
|
||||
|
||||
this._setValues = setValues;
|
||||
}
|
||||
|
||||
static decodeSet (setValues: SetValues, value: Array<string> | Uint8Array | number = 0): Array<string> {
|
||||
if (isU8a(value)) {
|
||||
return Set.decodeSet(setValues, value[0]);
|
||||
} 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 result;
|
||||
}, [] as Array<string>);
|
||||
}
|
||||
|
||||
const result = Object.keys(setValues).reduce((result, key) => {
|
||||
if ((value & setValues[key]) === setValues[key]) {
|
||||
result.push(key);
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [] as Array<string>);
|
||||
const computed = Set.encodeSet(setValues, result);
|
||||
|
||||
if (value !== computed) {
|
||||
console.error(`Mismatch decoding '${value}', computed as '${computed}' with ${result}`);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static encodeSet (setValues: SetValues, value: Array<string>): number {
|
||||
return value.reduce((result, value) => {
|
||||
return result | (setValues[value] || 0);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
get encodedLength (): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
get isEmpty (): boolean {
|
||||
return this.values.length === 0;
|
||||
}
|
||||
|
||||
get values (): Array<string> {
|
||||
return this.raw;
|
||||
}
|
||||
|
||||
get valueEncoded (): number {
|
||||
return Set.encodeSet(this._setValues, this.raw);
|
||||
}
|
||||
|
||||
toJSON (): any {
|
||||
return this.values;
|
||||
}
|
||||
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return new Uint8Array(this.valueEncoded);
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
return `[${this.values.map((value) => value).join(', ')}]`;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,11 @@
|
||||
|
||||
// These are the base codec types, generally used for construction
|
||||
export { default as Base } from './Base';
|
||||
export { default as Compact } from './Compact';
|
||||
export { default as Enum } from './Enum';
|
||||
export { default as EnumType } from './EnumType';
|
||||
export { default as Option } from './Option';
|
||||
export { default as Set } from './Set';
|
||||
export { default as Struct } from './Struct';
|
||||
export { default as Tuple } from './Tuple';
|
||||
export { default as Vector } from './Vector';
|
||||
|
||||
@@ -43,8 +43,7 @@ export { default as Method } from './Method';
|
||||
export { default as MisbehaviorReport } from './MisbehaviorReport';
|
||||
export { default as Moment } from './Moment';
|
||||
export { default as NewAccountOutcome } from './NewAccountOutcome';
|
||||
// NOTE only used internally atm
|
||||
// export { default as Null } from './Null';
|
||||
export { default as Null } from './Null';
|
||||
// NOTE Nonce is renamed to Index
|
||||
export { default as Index } from './Nonce';
|
||||
export { default as Origin } from './Origin';
|
||||
|
||||
Reference in New Issue
Block a user