Support for Option<bool> 1-byte encoding (#4852)

* Support for Option<bool> 1-byte encoding

* Adjust for linting
This commit is contained in:
Jaco
2022-05-26 08:53:38 +03:00
committed by GitHub
parent 4dad961106
commit 5a90d02f1f
11 changed files with 174 additions and 11 deletions
@@ -20,7 +20,7 @@ function traverseLinks (api: DeriveApi, head: AccountId32 | string): Observable<
),
tap((node: Option<PalletBagsListListNode>): void => {
setTimeout((): void => {
node.isSome && (node.value as PalletBagsListListNode).next.isSome
node.isSome && node.value.next.isSome
? subject.next(node.unwrap().next.unwrap())
: subject.complete();
}, 0);
+1 -1
View File
@@ -131,7 +131,7 @@ export class Option<T extends Codec> implements IOption<T> {
/**
* @description The actual value for the Option
*/
public get value (): Codec {
public get value (): T {
return this.#raw;
}
@@ -0,0 +1,47 @@
// Copyright 2017-2022 @polkadot/types-codec authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { TypeRegistry } from '@polkadot/types';
import { OptionBool } from '@polkadot/types-codec';
describe('OptionBool', (): void => {
const registry = new TypeRegistry();
describe('decodes', (): void => {
it('decodes none', (): void => {
expect(new OptionBool(registry).toJSON()).toEqual(null);
});
it('decodes true', (): void => {
expect(new OptionBool(registry, true).toJSON()).toEqual(true);
});
it('decodes false', (): void => {
expect(new OptionBool(registry, false).toJSON()).toEqual(false);
});
});
describe('encodes', (): void => {
it('encodes none', (): void => {
expect(new OptionBool(registry).toU8a()).toEqual(new Uint8Array([0]));
});
it('encodes true', (): void => {
expect(new OptionBool(registry, true).toU8a()).toEqual(new Uint8Array([1]));
});
it('encodes false', (): void => {
expect(new OptionBool(registry, false).toU8a()).toEqual(new Uint8Array([2]));
});
});
it('has a sane toRawType representation', (): void => {
expect(new OptionBool(registry).toRawType()).toEqual('Option<bool>');
});
it('has a sane inspect', (): void => {
expect(new OptionBool(registry, true).inspect()).toEqual({
outer: [new Uint8Array([1])]
});
});
});
@@ -0,0 +1,98 @@
// Copyright 2017-2022 @polkadot/types-codec authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { HexString } from '@polkadot/util/types';
import type { AnyBool, Inspect, Registry } from '../types';
import { isHex, isU8a, u8aToU8a } from '@polkadot/util';
import { Option } from '../base/Option';
import { bool as Bool } from '../native/Bool';
function decodeU8a (registry: Registry, value: Uint8Array): null | Bool {
// Encoded as -
// - 0 = None
// - 1 = True
// - 2 = False
return value[0] === 0
? null
: new Bool(registry, value[0] === 1);
}
/**
* @name OptionBool
* @description A specific implementation of Option<bool> than allows for single-byte encoding
*/
export class OptionBool extends Option<Bool> {
constructor (registry: Registry, value?: Option<Bool> | AnyBool | Uint8Array | HexString | null) {
super(
registry,
Bool,
isU8a(value) || isHex(value)
? decodeU8a(registry, u8aToU8a(value))
: value
);
}
/**
* @description The length of the value when encoded as a Uint8Array
*/
public override get encodedLength (): number {
return 1;
}
/**
* @description The length of the initial encoded value (Only available when constructed from a Uint8Array)
*/
public override get initialU8aLength (): number {
return 1;
}
/**
* @description Checks if the value is an empty value (always false)
*/
public get isFalse (): boolean {
return this.isSome
? !this.value.valueOf()
: false;
}
/**
* @description Checks if the value is an empty value (always false)
*/
public get isTrue (): boolean {
return this.isSome
? this.value.valueOf()
: false;
}
/**
* @description Returns a breakdown of the hex encoding for this Codec
*/
override inspect (): Inspect {
return { outer: [this.toU8a()] };
}
/**
* @description Returns the base runtime type name for this instance
*/
public override toRawType (isBare?: boolean): string {
return isBare
? 'bool'
: 'Option<bool>';
}
/**
* @description Encodes the value as a Uint8Array as per the SCALE specifications
* @param isBare true when the value has none of the type-specific prefixes (internal)
*/
public override toU8a (isBare?: boolean): Uint8Array {
if (isBare) {
return super.toU8a(true);
}
return this.isSome
? new Uint8Array([this.isTrue ? 1 : 2])
: new Uint8Array([0]);
}
}
@@ -8,6 +8,7 @@ export { Bytes } from './Bytes';
export { HashMap } from './HashMap';
export { Linkage } from './Linkage';
export { CodecMap, CodecMap as Map } from './Map';
export { OptionBool } from './OptionBool';
export { Range } from './Range';
export { RangeInclusive } from './RangeInclusive';
export { Type } from './Type';
+10 -3
View File
@@ -4,7 +4,7 @@
import type { Codec, CodecClass, Registry, U8aBitLength, UIntBitLength } from '@polkadot/types-codec/types';
import type { TypeDef } from '../types';
import { BTreeMap, BTreeSet, Bytes, CodecSet, Compact, DoNotConstruct, Enum, HashMap, Int, Null, Option, Range, RangeInclusive, Result, Struct, Tuple, U8aFixed, UInt, Vec, VecFixed, WrapperKeepOpaque, WrapperOpaque } from '@polkadot/types-codec';
import { BTreeMap, BTreeSet, Bytes, CodecSet, Compact, DoNotConstruct, Enum, HashMap, Int, Null, Option, OptionBool, Range, RangeInclusive, Result, Struct, Tuple, U8aFixed, UInt, Vec, VecFixed, WrapperKeepOpaque, WrapperOpaque } from '@polkadot/types-codec';
import { assert, isNumber, stringify } from '@polkadot/util';
import { TypeDefInfo } from '../types';
@@ -115,8 +115,15 @@ const infoMapping: Record<TypeDefInfo, (registry: Registry, value: TypeDef) => C
[TypeDefInfo.Null]: (registry: Registry, _: TypeDef): CodecClass<Codec> =>
Null,
[TypeDefInfo.Option]: (registry: Registry, value: TypeDef): CodecClass<Codec> =>
createWithSub(Option, value),
[TypeDefInfo.Option]: (registry: Registry, value: TypeDef): CodecClass<Codec> => {
assert(value.sub && !Array.isArray(value.sub), 'Expected type information for Option');
return (
value.sub.type === 'bool'
? OptionBool
: createWithSub(Option, value)
);
},
[TypeDefInfo.Plain]: (registry: Registry, value: TypeDef): CodecClass<Codec> =>
registry.getOrUnknown(value.type),
@@ -774,9 +774,18 @@ export class PortableRegistry extends Struct implements ILookup {
const specialVariant = path[0].toString();
if (specialVariant === 'Option') {
const sub = this.#createSiDef(params[0].type.unwrap());
if (sub.type === 'bool') {
return withTypeString(this.registry, {
info: TypeDefInfo.Plain,
type: 'OptionBool'
});
}
return withTypeString(this.registry, {
info: TypeDefInfo.Option,
sub: this.#createSiDef(params[0].type.unwrap())
sub
});
} else if (specialVariant === 'Result') {
return withTypeString(this.registry, {
+1 -1
View File
@@ -4,7 +4,7 @@
/**
* @summary Type definitions that are used in the system
*/
export { BitVec, bool, Bool, Bytes, i8, I8, i16, I16, i32, I32, i64, I64, i128, I128, i256, I256, Null, Text, Type, u8, U8, u16, U16, u32, U32, u64, U64, u128, U128, u256, U256, usize, USize } from '@polkadot/types-codec';
export { BitVec, bool, Bool, Bytes, i8, I8, i16, I16, i32, I32, i64, I64, i128, I128, i256, I256, Null, OptionBool, Text, Type, u8, U8, u16, U16, u32, U32, u64, U64, u128, U128, u256, U256, usize, USize } from '@polkadot/types-codec';
export { Data } from './Data';
export { StorageKey } from './StorageKey';
+2 -2
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { InterfaceTypes } from '@polkadot/types/types';
import type { BTreeMap, BTreeSet, Bytes, CodecSet, Compact, Enum, HashMap, Linkage, Null, Option, Range, RangeInclusive, Result, Struct, u8, U8aFixed, Vec, VecFixed } from '@polkadot/types-codec';
import type { bool, BTreeMap, BTreeSet, Bytes, CodecSet, Compact, Enum, HashMap, Linkage, Null, Option, OptionBool, Range, RangeInclusive, Result, Struct, u8, U8aFixed, Vec, VecFixed } from '@polkadot/types-codec';
import type { Codec, ICompact, IEnum, IMap, IMethod, INumber, IOption, IResult, ISet, IStruct, ITuple, IU8a, IVec } from '@polkadot/types-codec/types';
export type DetectCodec<T extends Codec, K extends string> =
@@ -37,7 +37,7 @@ export type __MapWrapOne<C extends Codec> = {
'BTreeSet<': BTreeSet<C>;
'Compact<': C extends INumber ? Compact<C> : Codec;
'Linkage<': Linkage<C>;
'Option<': Option<C>;
'Option<': C extends bool ? OptionBool : Option<C>;
'Range<': C extends INumber ? Range<C> : Codec;
'RangeInclusive<': C extends INumber ? RangeInclusive<C> : Codec;
'Vec<': C extends u8 ? Bytes : Vec<C>;
+2 -2
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { Observable } from 'rxjs';
import type { BitVec, Bool, bool, Bytes, I8, i8, I16, i16, I32, i32, I64, i64, I128, i128, I256, i256, Json, Null, Raw, Text, Type, U8, u8, U16, u16, U32, u32, U64, u64, U128, u128, U256, u256, USize, usize } from '@polkadot/types-codec';
import type { BitVec, Bool, bool, Bytes, I8, i8, I16, i16, I32, i32, I64, i64, I128, i128, I256, i256, Json, Null, OptionBool, Raw, Text, Type, U8, u8, U16, u16, U32, u32, U64, u64, U128, u128, U256, u256, USize, usize } from '@polkadot/types-codec';
import type { RegistryTypes } from '@polkadot/types-codec/types';
import type { BN } from '@polkadot/util';
import type { GenericExtrinsic, GenericExtrinsicEra, GenericExtrinsicPayload, GenericSignerPayload } from '../extrinsic';
@@ -18,7 +18,7 @@ export type { Registry, RegistryError, RegistryTypes } from '@polkadot/types-cod
export interface InterfaceTypes {
// base codec
BitVec: BitVec, Bool: Bool, Bytes: Bytes, I128: I128, I16: I16, I256: I256, I32: I32, I64: I64, I8: I8, Json: Json, Null: Null, Raw: Raw, Text: Text, Type: Type, U128: U128, U16: U16, U256: U256, U32: U32, U64: U64, U8: U8, USize: USize, bool: bool, i128: i128, i16: i16, i256: i256, i32: i32, i64: i64, i8: i8, u128: u128, u16: u16, u256: u256, u32: u32, u64: u64, u8: u8, usize: usize,
BitVec: BitVec, Bool: Bool, Bytes: Bytes, I128: I128, I16: I16, I256: I256, I32: I32, I64: I64, I8: I8, Json: Json, Null: Null, OptionBool: OptionBool, Raw: Raw, Text: Text, Type: Type, U128: U128, U16: U16, U256: U256, U32: U32, U64: U64, U8: U8, USize: USize, bool: bool, i128: i128, i16: i16, i256: i256, i32: i32, i64: i64, i8: i8, u128: u128, u16: u16, u256: u256, u32: u32, u64: u64, u8: u8, usize: usize,
// extrinsic
Extrinsic: GenericExtrinsic, ExtrinsicEra: GenericExtrinsicEra, ExtrinsicPayload: GenericExtrinsicPayload, SignerPayload: GenericSignerPayload,
// generic