@pezkuwi/types-codec 16.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/build/abstract/Array.d.ts +89 -0
- package/build/abstract/Base.d.ts +75 -0
- package/build/abstract/Int.d.ts +80 -0
- package/build/abstract/Object.d.ts +67 -0
- package/build/abstract/index.d.ts +3 -0
- package/build/base/Compact.d.ts +88 -0
- package/build/base/DoNotConstruct.d.ts +63 -0
- package/build/base/Enum.d.ts +118 -0
- package/build/base/Int.d.ts +16 -0
- package/build/base/Null.d.ts +56 -0
- package/build/base/Option.d.ts +94 -0
- package/build/base/Result.d.ts +38 -0
- package/build/base/Tuple.d.ts +42 -0
- package/build/base/UInt.d.ts +15 -0
- package/build/base/Vec.d.ts +28 -0
- package/build/base/VecAny.d.ts +15 -0
- package/build/base/VecFixed.d.ts +30 -0
- package/build/base/index.d.ts +12 -0
- package/build/bundle.d.ts +7 -0
- package/build/extended/BTreeMap.d.ts +5 -0
- package/build/extended/BTreeSet.d.ts +64 -0
- package/build/extended/BitVec.d.ts +37 -0
- package/build/extended/Bytes.d.ts +29 -0
- package/build/extended/HashMap.d.ts +5 -0
- package/build/extended/Linkage.d.ts +37 -0
- package/build/extended/Map.d.ts +59 -0
- package/build/extended/OptionBool.d.ts +36 -0
- package/build/extended/Range.d.ts +29 -0
- package/build/extended/RangeInclusive.d.ts +6 -0
- package/build/extended/Type.d.ts +16 -0
- package/build/extended/U8aFixed.d.ts +16 -0
- package/build/extended/WrapperKeepOpaque.d.ts +40 -0
- package/build/extended/WrapperOpaque.d.ts +10 -0
- package/build/extended/index.d.ts +14 -0
- package/build/index.d.ts +2 -0
- package/build/native/Bool.d.ts +71 -0
- package/build/native/Date.d.ts +84 -0
- package/build/native/Float.d.ts +68 -0
- package/build/native/Json.d.ts +69 -0
- package/build/native/Raw.d.ts +87 -0
- package/build/native/Set.d.ts +84 -0
- package/build/native/Struct.d.ts +106 -0
- package/build/native/Text.d.ts +77 -0
- package/build/native/index.d.ts +8 -0
- package/build/packageDetect.d.ts +1 -0
- package/build/packageInfo.d.ts +6 -0
- package/build/primitive/F32.d.ts +11 -0
- package/build/primitive/F64.d.ts +11 -0
- package/build/primitive/I128.d.ts +11 -0
- package/build/primitive/I16.d.ts +11 -0
- package/build/primitive/I256.d.ts +11 -0
- package/build/primitive/I32.d.ts +11 -0
- package/build/primitive/I64.d.ts +11 -0
- package/build/primitive/I8.d.ts +11 -0
- package/build/primitive/ISize.d.ts +12 -0
- package/build/primitive/U128.d.ts +11 -0
- package/build/primitive/U16.d.ts +11 -0
- package/build/primitive/U256.d.ts +11 -0
- package/build/primitive/U32.d.ts +11 -0
- package/build/primitive/U64.d.ts +11 -0
- package/build/primitive/U8.d.ts +11 -0
- package/build/primitive/USize.d.ts +12 -0
- package/build/primitive/index.d.ts +16 -0
- package/build/types/codec.d.ts +113 -0
- package/build/types/helpers.d.ts +27 -0
- package/build/types/index.d.ts +4 -0
- package/build/types/interfaces.d.ts +74 -0
- package/build/types/registry.d.ts +67 -0
- package/build/utils/compareArray.d.ts +1 -0
- package/build/utils/compareMap.d.ts +1 -0
- package/build/utils/compareSet.d.ts +1 -0
- package/build/utils/decodeU8a.d.ts +26 -0
- package/build/utils/index.d.ts +8 -0
- package/build/utils/sanitize.d.ts +15 -0
- package/build/utils/sortValues.d.ts +12 -0
- package/build/utils/toConstructors.d.ts +16 -0
- package/build/utils/typesToMap.d.ts +2 -0
- package/build/utils/util.d.ts +3 -0
- package/package.json +34 -0
- package/src/abstract/Array.ts +213 -0
- package/src/abstract/Base.ts +129 -0
- package/src/abstract/Int.ts +271 -0
- package/src/abstract/Object.ts +99 -0
- package/src/abstract/index.ts +6 -0
- package/src/base/Compact.spec.ts +99 -0
- package/src/base/Compact.ts +198 -0
- package/src/base/DoNotConstruct.spec.ts +23 -0
- package/src/base/DoNotConstruct.ts +118 -0
- package/src/base/Enum.spec.ts +487 -0
- package/src/base/Enum.ts +460 -0
- package/src/base/Int.spec.ts +225 -0
- package/src/base/Int.ts +34 -0
- package/src/base/Null.spec.ts +41 -0
- package/src/base/Null.ts +96 -0
- package/src/base/Option.spec.ts +216 -0
- package/src/base/Option.ts +275 -0
- package/src/base/Result.spec.ts +64 -0
- package/src/base/Result.ts +79 -0
- package/src/base/Tuple.spec.ts +161 -0
- package/src/base/Tuple.ts +149 -0
- package/src/base/UInt.spec.ts +192 -0
- package/src/base/UInt.ts +30 -0
- package/src/base/Vec.spec.ts +224 -0
- package/src/base/Vec.ts +133 -0
- package/src/base/VecAny.ts +23 -0
- package/src/base/VecFixed.spec.ts +78 -0
- package/src/base/VecFixed.ts +92 -0
- package/src/base/index.ts +15 -0
- package/src/bundle.ts +13 -0
- package/src/checkTypes.manual.ts +12 -0
- package/src/extended/BTreeMap.spec.ts +245 -0
- package/src/extended/BTreeMap.ts +16 -0
- package/src/extended/BTreeSet.spec.ts +260 -0
- package/src/extended/BTreeSet.ts +233 -0
- package/src/extended/BitVec.spec.ts +97 -0
- package/src/extended/BitVec.ts +137 -0
- package/src/extended/Bytes.spec.ts +75 -0
- package/src/extended/Bytes.ts +88 -0
- package/src/extended/HashMap.spec.ts +36 -0
- package/src/extended/HashMap.ts +16 -0
- package/src/extended/Linkage.spec.ts +43 -0
- package/src/extended/Linkage.ts +81 -0
- package/src/extended/Map.spec.ts +123 -0
- package/src/extended/Map.ts +255 -0
- package/src/extended/OptionBool.spec.ts +49 -0
- package/src/extended/OptionBool.ts +93 -0
- package/src/extended/Range.spec.ts +37 -0
- package/src/extended/Range.ts +56 -0
- package/src/extended/RangeInclusive.ts +20 -0
- package/src/extended/Type.spec.ts +118 -0
- package/src/extended/Type.ts +29 -0
- package/src/extended/U8aFixed.spec.ts +117 -0
- package/src/extended/U8aFixed.ts +57 -0
- package/src/extended/WrapperKeepOpaque.spec.ts +101 -0
- package/src/extended/WrapperKeepOpaque.ts +128 -0
- package/src/extended/WrapperOpaque.spec.ts +58 -0
- package/src/extended/WrapperOpaque.ts +27 -0
- package/src/extended/index.ts +17 -0
- package/src/index.ts +6 -0
- package/src/mod.ts +4 -0
- package/src/native/Bool.spec.ts +74 -0
- package/src/native/Bool.ts +137 -0
- package/src/native/Date.spec.ts +85 -0
- package/src/native/Date.ts +169 -0
- package/src/native/Float.spec.ts +51 -0
- package/src/native/Float.ts +136 -0
- package/src/native/Json.ts +147 -0
- package/src/native/Raw.spec.ts +113 -0
- package/src/native/Raw.ts +171 -0
- package/src/native/Set.spec.ts +116 -0
- package/src/native/Set.ts +269 -0
- package/src/native/Struct.data.ts +4 -0
- package/src/native/Struct.spec.ts +411 -0
- package/src/native/Struct.ts +338 -0
- package/src/native/Text.spec.ts +85 -0
- package/src/native/Text.ts +184 -0
- package/src/native/index.ts +11 -0
- package/src/packageDetect.ts +11 -0
- package/src/packageInfo.ts +6 -0
- package/src/primitive/F32.ts +14 -0
- package/src/primitive/F64.ts +14 -0
- package/src/primitive/I128.ts +14 -0
- package/src/primitive/I16.ts +14 -0
- package/src/primitive/I256.ts +14 -0
- package/src/primitive/I32.ts +14 -0
- package/src/primitive/I64.ts +14 -0
- package/src/primitive/I8.ts +14 -0
- package/src/primitive/ISize.ts +21 -0
- package/src/primitive/U128.ts +14 -0
- package/src/primitive/U16.ts +14 -0
- package/src/primitive/U256.ts +14 -0
- package/src/primitive/U32.ts +14 -0
- package/src/primitive/U64.ts +14 -0
- package/src/primitive/U8.ts +14 -0
- package/src/primitive/USize.ts +21 -0
- package/src/primitive/index.ts +19 -0
- package/src/test/performance.ts +61 -0
- package/src/types/codec.ts +140 -0
- package/src/types/helpers.ts +50 -0
- package/src/types/index.ts +7 -0
- package/src/types/interfaces.ts +98 -0
- package/src/types/registry.ts +86 -0
- package/src/utils/compareArray.ts +22 -0
- package/src/utils/compareMap.ts +40 -0
- package/src/utils/compareSet.ts +23 -0
- package/src/utils/decodeU8a.ts +123 -0
- package/src/utils/index.ts +11 -0
- package/src/utils/sanitize.spec.ts +89 -0
- package/src/utils/sanitize.ts +290 -0
- package/src/utils/sortValues.ts +103 -0
- package/src/utils/toConstructors.ts +46 -0
- package/src/utils/typesToMap.ts +14 -0
- package/src/utils/util.ts +8 -0
- package/tsconfig.build.json +16 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.spec.json +21 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/types-codec authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { TypeRegistry } from '@pezkuwi/types';
|
|
7
|
+
import { Null } from '@pezkuwi/types-codec';
|
|
8
|
+
|
|
9
|
+
describe('Null', (): void => {
|
|
10
|
+
const registry = new TypeRegistry();
|
|
11
|
+
|
|
12
|
+
it('compares against null', (): void => {
|
|
13
|
+
expect(new Null(registry).eq(null)).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('compares against Null', (): void => {
|
|
17
|
+
expect(new Null(registry).eq(new Null(registry))).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('compares against other (failed)', (): void => {
|
|
21
|
+
expect(new Null(registry).eq()).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('has no hash', (): void => {
|
|
25
|
+
expect(
|
|
26
|
+
() => new Null(registry).hash
|
|
27
|
+
).toThrow();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('isEmpty', (): void => {
|
|
31
|
+
expect(new Null(registry).isEmpty).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('has an empty hex', (): void => {
|
|
35
|
+
expect(new Null(registry).toHex()).toEqual('0x');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('has a Null type', (): void => {
|
|
39
|
+
expect(new Null(registry).toRawType()).toEqual('Null');
|
|
40
|
+
});
|
|
41
|
+
});
|
package/src/base/Null.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/types-codec authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { HexString } from '@pezkuwi/util/types';
|
|
5
|
+
import type { Codec, Inspect, IU8a, Registry } from '../types/index.js';
|
|
6
|
+
|
|
7
|
+
import { isNull } from '@pezkuwi/util';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @name Null
|
|
11
|
+
* @description
|
|
12
|
+
* Implements a type that does not contain anything (apart from `null`)
|
|
13
|
+
*/
|
|
14
|
+
export class Null implements Codec {
|
|
15
|
+
readonly encodedLength = 0;
|
|
16
|
+
readonly isEmpty = true;
|
|
17
|
+
readonly registry: Registry;
|
|
18
|
+
|
|
19
|
+
public createdAtHash?: IU8a;
|
|
20
|
+
public initialU8aLength = 0;
|
|
21
|
+
public isStorageFallback?: boolean;
|
|
22
|
+
|
|
23
|
+
constructor (registry: Registry) {
|
|
24
|
+
this.registry = registry;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @description returns a hash of the contents
|
|
29
|
+
*/
|
|
30
|
+
public get hash (): IU8a {
|
|
31
|
+
throw new Error('.hash is not implemented on Null');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @description Compares the value of the input to see if there is a match
|
|
36
|
+
*/
|
|
37
|
+
public eq (other?: unknown): boolean {
|
|
38
|
+
return other instanceof Null || isNull(other);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @description Returns a breakdown of the hex encoding for this Codec
|
|
43
|
+
*/
|
|
44
|
+
public inspect (): Inspect {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @description Returns a hex string representation of the value
|
|
50
|
+
*/
|
|
51
|
+
public toHex (): HexString {
|
|
52
|
+
return '0x';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @description Converts the Object to to a human-friendly JSON, with additional fields, expansion and formatting of information
|
|
57
|
+
*/
|
|
58
|
+
public toHuman (): null {
|
|
59
|
+
return this.toJSON();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @description Converts the Object to JSON, typically used for RPC transfers
|
|
64
|
+
*/
|
|
65
|
+
public toJSON (): null {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @description Converts the value in a best-fit primitive form
|
|
71
|
+
*/
|
|
72
|
+
public toPrimitive (): null {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @description Returns the base runtime type name for this instance
|
|
78
|
+
*/
|
|
79
|
+
public toRawType (): string {
|
|
80
|
+
return 'Null';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @description Returns the string representation of the value
|
|
85
|
+
*/
|
|
86
|
+
public toString (): string {
|
|
87
|
+
return '';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @description Encodes the value as a Uint8Array as per the SCALE specifications
|
|
92
|
+
*/
|
|
93
|
+
public toU8a (_isBare?: boolean): Uint8Array {
|
|
94
|
+
return new Uint8Array();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/types-codec authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { TypeRegistry } from '@pezkuwi/types';
|
|
7
|
+
import { bool, Bytes, Null, Option, Text, U32 } from '@pezkuwi/types-codec';
|
|
8
|
+
|
|
9
|
+
const registry = new TypeRegistry();
|
|
10
|
+
|
|
11
|
+
const testDecode = (type: string, input: any, expected: string): void =>
|
|
12
|
+
it(`can decode from ${type}`, (): void => {
|
|
13
|
+
const o = new Option(registry, Text, input);
|
|
14
|
+
|
|
15
|
+
expect(o.toString()).toBe(expected);
|
|
16
|
+
expect(o.isNone).toBe(!expected.length);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const testEncode = (to: 'toHex' | 'toString' | 'toU8a', expected: any): void =>
|
|
20
|
+
it(`can encode ${to}`, (): void => {
|
|
21
|
+
const e = new Option(registry, Text, 'foo');
|
|
22
|
+
|
|
23
|
+
expect(e[to]()).toEqual(expected);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('Option', (): void => {
|
|
27
|
+
it('converts undefined/null to empty', (): void => {
|
|
28
|
+
expect(new Option(registry, Text, undefined).isNone).toBe(true);
|
|
29
|
+
expect(new Option(registry, Text, null).isNone).toBe(true);
|
|
30
|
+
expect(new Option(registry, Text, 'test').isNone).toBe(false);
|
|
31
|
+
expect(new Option(registry, Text, '0x').isNone).toBe(true);
|
|
32
|
+
expect(new Option(registry, '()', null).isNone).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('can wrap an Option<Null>/Option<()>', (): void => {
|
|
36
|
+
[
|
|
37
|
+
new Option(registry, Null, new Null(registry)),
|
|
38
|
+
new Option(registry, '()', new Null(registry))
|
|
39
|
+
].forEach((test): void => {
|
|
40
|
+
expect(test.isSome).toBe(true);
|
|
41
|
+
expect(test.isNone).toBe(false);
|
|
42
|
+
expect(test.isEmpty).toBe(false);
|
|
43
|
+
expect(test.toU8a()).toEqual(new Uint8Array([1]));
|
|
44
|
+
expect(test.unwrap().toHex()).toEqual('0x');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('can decode a nested Option', (): void => {
|
|
49
|
+
expect(
|
|
50
|
+
new Option(
|
|
51
|
+
registry,
|
|
52
|
+
Option.with(Option.with(Text)),
|
|
53
|
+
new Option(
|
|
54
|
+
registry,
|
|
55
|
+
Option.with(Text),
|
|
56
|
+
new Option(
|
|
57
|
+
registry,
|
|
58
|
+
Text,
|
|
59
|
+
new Uint8Array([1, 3 << 2, 66, 67, 68])
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
).toU8a()
|
|
63
|
+
).toEqual(new Uint8Array([1, 1, 1, 3 << 2, 66, 67, 68]));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('can convert between different Some/None', (): void => {
|
|
67
|
+
const def = '{ "foo":"Text", "zar":"Text" }';
|
|
68
|
+
const none = new Option(registry, def, null);
|
|
69
|
+
const some = new Option(registry, def, new Option(registry, def, { foo: 'a', zar: 'b' }));
|
|
70
|
+
|
|
71
|
+
expect(new Option(registry, def, none).isNone).toBe(true);
|
|
72
|
+
expect(new Option(registry, def, some).isNone).toBe(false);
|
|
73
|
+
expect(new Option(registry, def, some).unwrap().toHuman()).toEqual({ foo: 'a', zar: 'b' });
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('correctly handles booleans', (): void => {
|
|
77
|
+
expect(new Option(registry, bool).isNone).toBe(true);
|
|
78
|
+
expect(new Option(registry, bool, true).isSome).toBe(true);
|
|
79
|
+
expect(new Option(registry, bool, true).unwrap().isTrue).toBe(true);
|
|
80
|
+
expect(new Option(registry, bool, false).isSome).toBe(true);
|
|
81
|
+
expect(new Option(registry, bool, false).unwrap().isTrue).toBe(false);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('converts an option to an option', (): void => {
|
|
85
|
+
expect(
|
|
86
|
+
new Option(registry, Text, new Option(registry, Text, 'hello')).toString()
|
|
87
|
+
).toEqual('hello');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('converts an option to an option (strings)', (): void => {
|
|
91
|
+
expect(
|
|
92
|
+
new Option(registry, 'Text', new Option(registry, 'Text', 'hello')).toString()
|
|
93
|
+
).toEqual('hello');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('converts correctly from hex with toHex (Bytes)', (): void => {
|
|
97
|
+
// Option<Bytes> for a parachain head, however, this is effectively an
|
|
98
|
+
// Option<Option<Bytes>> (hence the length, since it is from storage)
|
|
99
|
+
const HEX = '0x210100000000000000000000000000000000000000000000000000000000000000000000000000000000011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce';
|
|
100
|
+
|
|
101
|
+
// watch the hex prefix and length
|
|
102
|
+
expect(
|
|
103
|
+
new Option(registry, Bytes, HEX).toHex().substring(6)
|
|
104
|
+
).toEqual(HEX.substring(2));
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('converts correctly from hex with toNumber (U64)', (): void => {
|
|
108
|
+
const HEX = '0x12345678';
|
|
109
|
+
|
|
110
|
+
expect(
|
|
111
|
+
new Option(registry, U32, HEX).unwrap().toNumber()
|
|
112
|
+
).toEqual(0x12345678);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('decodes reusing instanciated inputs', (): void => {
|
|
116
|
+
const foo = new Text(registry, 'bar');
|
|
117
|
+
|
|
118
|
+
expect(
|
|
119
|
+
(new Option(registry, Text, foo)).value
|
|
120
|
+
).toBe(foo);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
testDecode('string (with)', 'foo', 'foo');
|
|
124
|
+
testDecode('string (without)', undefined, '');
|
|
125
|
+
testDecode('Uint8Array (with)', Uint8Array.from([1, 12, 102, 111, 111]), 'foo');
|
|
126
|
+
testDecode('Uint8Array (without)', Uint8Array.from([0]), '');
|
|
127
|
+
|
|
128
|
+
testEncode('toHex', '0x0c666f6f');
|
|
129
|
+
testEncode('toString', 'foo');
|
|
130
|
+
testEncode('toU8a', Uint8Array.from([1, 12, 102, 111, 111]));
|
|
131
|
+
|
|
132
|
+
it('has empty toString() (undefined)', (): void => {
|
|
133
|
+
expect(
|
|
134
|
+
new Option(registry, Text).toString()
|
|
135
|
+
).toEqual('');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('has value toString() (provided)', (): void => {
|
|
139
|
+
expect(
|
|
140
|
+
new Option(registry, Text, new Uint8Array([1, 4 << 2, 49, 50, 51, 52])).toString()
|
|
141
|
+
).toEqual('1234');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('converts toU8a() with', (): void => {
|
|
145
|
+
expect(
|
|
146
|
+
new Option(registry, Text, '1234').toU8a()
|
|
147
|
+
).toEqual(new Uint8Array([1, 4 << 2, 49, 50, 51, 52]));
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('allows bare specifiers on toU8a', (): void => {
|
|
151
|
+
expect(
|
|
152
|
+
new Option(registry, Text, '1234').toU8a(true)
|
|
153
|
+
).toEqual(new Uint8Array([49, 50, 51, 52]));
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('converts toU8a() without', (): void => {
|
|
157
|
+
expect(
|
|
158
|
+
new Option(registry, Text).toU8a()
|
|
159
|
+
).toEqual(new Uint8Array([0]));
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('converts toJSON() as null without', (): void => {
|
|
163
|
+
expect(
|
|
164
|
+
new Option(registry, Text).toJSON()
|
|
165
|
+
).toEqual(null);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('converts toJSON() as non-null with Bytes', (): void => {
|
|
169
|
+
expect(
|
|
170
|
+
new Option(registry, Bytes, 'abcde').toJSON()
|
|
171
|
+
).toEqual('0x6162636465');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('converts toJSON() as non-null with Text', (): void => {
|
|
175
|
+
expect(
|
|
176
|
+
new Option(registry, Text, 'abcde').toJSON()
|
|
177
|
+
).toEqual('abcde');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('utils', (): void => {
|
|
181
|
+
const test = new Option(registry, Text, '1234');
|
|
182
|
+
|
|
183
|
+
it('compares against other option', (): void => {
|
|
184
|
+
expect(test.eq(new Option(registry, Text, '1234'))).toBe(true);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('compares against raw value', (): void => {
|
|
188
|
+
expect(test.eq('1234')).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('unwrapOr to specified if empty', (): void => {
|
|
192
|
+
expect(new Option(registry, Text).unwrapOr('6789').toString()).toEqual('6789');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('unwrapOr to specified if non-empty', (): void => {
|
|
196
|
+
expect(new Option(registry, Text, '1234').unwrapOr(null)?.toString()).toEqual('1234');
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('unwrapOrDefault to default if empty', (): void => {
|
|
200
|
+
expect(new Option(registry, U32).unwrapOrDefault().toNumber()).toEqual(0);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('unwrapOrDefault to specified if non-empty', (): void => {
|
|
204
|
+
expect(new Option(registry, U32, '1234').unwrapOrDefault().toNumber()).toEqual(1234);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('has a sane inspect', (): void => {
|
|
208
|
+
expect(
|
|
209
|
+
new Option(registry, U32, '1234').inspect()
|
|
210
|
+
).toEqual({
|
|
211
|
+
inner: undefined,
|
|
212
|
+
outer: [new Uint8Array([0x01]), new Uint8Array([210, 4, 0, 0])]
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
});
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/types-codec authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { HexString } from '@pezkuwi/util/types';
|
|
5
|
+
import type { AnyJson, Codec, CodecClass, DefinitionSetter, Inspect, IOption, IU8a, Registry } from '../types/index.js';
|
|
6
|
+
|
|
7
|
+
import { identity, isCodec, isNull, isU8a, isUndefined, u8aToHex } from '@pezkuwi/util';
|
|
8
|
+
|
|
9
|
+
import { typeToConstructor } from '../utils/index.js';
|
|
10
|
+
import { Null } from './Null.js';
|
|
11
|
+
|
|
12
|
+
class None extends Null {
|
|
13
|
+
/**
|
|
14
|
+
* @description Returns the base runtime type name for this instance
|
|
15
|
+
*/
|
|
16
|
+
public override toRawType (): string {
|
|
17
|
+
return 'None';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** @internal */
|
|
22
|
+
function decodeOption (registry: Registry, Type: CodecClass, value?: unknown): Codec {
|
|
23
|
+
if (value instanceof Type) {
|
|
24
|
+
// don't re-create, use as it (which also caters for derived types)
|
|
25
|
+
return value;
|
|
26
|
+
} else if (value instanceof Option) {
|
|
27
|
+
if (value.value instanceof Type) {
|
|
28
|
+
// same instance, return it
|
|
29
|
+
return value.value;
|
|
30
|
+
} else if (value.isNone) {
|
|
31
|
+
// internal is None, we are also none
|
|
32
|
+
return new None(registry);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// convert the actual value into known
|
|
36
|
+
return new Type(registry, value.value);
|
|
37
|
+
} else if (isNull(value) || isUndefined(value) || value === '0x' || value instanceof None) {
|
|
38
|
+
// anything empty we pass as-is
|
|
39
|
+
return new None(registry);
|
|
40
|
+
} else if (isU8a(value)) {
|
|
41
|
+
// the isU8a check happens last in the if-tree - since the wrapped value
|
|
42
|
+
// may be an instance of it, so Type and Option checks go in first
|
|
43
|
+
return !value.length || value[0] === 0
|
|
44
|
+
? new None(registry)
|
|
45
|
+
: new Type(registry, value.subarray(1));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return new Type(registry, value);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @name Option
|
|
53
|
+
* @description
|
|
54
|
+
* An Option is an optional field. Basically the first byte indicates that there is
|
|
55
|
+
* is value to follow. If the byte is `1` there is an actual value. So the Option
|
|
56
|
+
* implements that - decodes, checks for optionality and wraps the required structure
|
|
57
|
+
* with a value if/as required/found.
|
|
58
|
+
*/
|
|
59
|
+
export class Option<T extends Codec> implements IOption<T> {
|
|
60
|
+
readonly registry: Registry;
|
|
61
|
+
|
|
62
|
+
public createdAtHash?: IU8a;
|
|
63
|
+
public initialU8aLength?: number;
|
|
64
|
+
public isStorageFallback?: boolean;
|
|
65
|
+
|
|
66
|
+
readonly #Type: CodecClass<T>;
|
|
67
|
+
readonly #raw: T;
|
|
68
|
+
|
|
69
|
+
constructor (registry: Registry, typeName: CodecClass<T> | string, value?: unknown, { definition, setDefinition = identity }: DefinitionSetter<CodecClass<T>> = {}) {
|
|
70
|
+
const Type = definition || setDefinition(typeToConstructor(registry, typeName));
|
|
71
|
+
const decoded = isU8a(value) && value.length && !isCodec(value)
|
|
72
|
+
? value[0] === 0
|
|
73
|
+
? new None(registry)
|
|
74
|
+
: new Type(registry, value.subarray(1))
|
|
75
|
+
: decodeOption(registry, Type, value);
|
|
76
|
+
|
|
77
|
+
this.registry = registry;
|
|
78
|
+
this.#Type = Type;
|
|
79
|
+
this.#raw = decoded as T;
|
|
80
|
+
|
|
81
|
+
if (decoded?.initialU8aLength) {
|
|
82
|
+
this.initialU8aLength = 1 + decoded.initialU8aLength;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public static with<O extends Codec> (Type: CodecClass<O> | string): CodecClass<Option<O>> {
|
|
87
|
+
let definition: CodecClass<O> | undefined;
|
|
88
|
+
|
|
89
|
+
const setDefinition = <T> (d: CodecClass<T>): CodecClass<T> => {
|
|
90
|
+
definition = d as unknown as CodecClass<O>;
|
|
91
|
+
|
|
92
|
+
return d;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return class extends Option<O> {
|
|
96
|
+
constructor (registry: Registry, value?: unknown) {
|
|
97
|
+
super(registry, Type, value, { definition, setDefinition });
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @description The length of the value when encoded as a Uint8Array
|
|
104
|
+
*/
|
|
105
|
+
public get encodedLength (): number {
|
|
106
|
+
// boolean byte (has value, doesn't have) along with wrapped length
|
|
107
|
+
return 1 + this.#raw.encodedLength;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @description returns a hash of the contents
|
|
112
|
+
*/
|
|
113
|
+
public get hash (): IU8a {
|
|
114
|
+
return this.registry.hash(this.toU8a());
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @description Checks if the Option has no value
|
|
119
|
+
*/
|
|
120
|
+
public get isEmpty (): boolean {
|
|
121
|
+
return this.isNone;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @description Checks if the Option has no value
|
|
126
|
+
*/
|
|
127
|
+
public get isNone (): boolean {
|
|
128
|
+
return this.#raw instanceof None;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @description Checks if the Option has a value
|
|
133
|
+
*/
|
|
134
|
+
public get isSome (): boolean {
|
|
135
|
+
return !this.isNone;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @description The actual value for the Option
|
|
140
|
+
*/
|
|
141
|
+
public get value (): T {
|
|
142
|
+
return this.#raw;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @description Compares the value of the input to see if there is a match
|
|
147
|
+
*/
|
|
148
|
+
public eq (other?: unknown): boolean {
|
|
149
|
+
if (other instanceof Option) {
|
|
150
|
+
return (this.isSome === other.isSome) && this.value.eq(other.value);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return this.value.eq(other);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @description Returns a breakdown of the hex encoding for this Codec
|
|
158
|
+
*/
|
|
159
|
+
public inspect (): Inspect {
|
|
160
|
+
if (this.isNone) {
|
|
161
|
+
return { outer: [new Uint8Array([0])] };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const { inner, outer = [] } = this.#raw.inspect();
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
inner,
|
|
168
|
+
outer: [new Uint8Array([1]), ...outer]
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @description Returns a hex string representation of the value
|
|
174
|
+
*/
|
|
175
|
+
public toHex (): HexString {
|
|
176
|
+
// This attempts to align with the JSON encoding - actually in this case
|
|
177
|
+
// the isSome value is correct, however the `isNone` may be problematic
|
|
178
|
+
return this.isNone
|
|
179
|
+
? '0x'
|
|
180
|
+
: u8aToHex(this.toU8a().subarray(1));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @description Converts the Object to to a human-friendly JSON, with additional fields, expansion and formatting of information
|
|
185
|
+
*/
|
|
186
|
+
public toHuman (isExtended?: boolean, disableAscii?: boolean): AnyJson {
|
|
187
|
+
return this.#raw.toHuman(isExtended, disableAscii);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* @description Converts the Object to JSON, typically used for RPC transfers
|
|
192
|
+
*/
|
|
193
|
+
public toJSON (): AnyJson {
|
|
194
|
+
return this.isNone
|
|
195
|
+
? null
|
|
196
|
+
: this.#raw.toJSON();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @description Converts the value in a best-fit primitive form
|
|
201
|
+
*/
|
|
202
|
+
public toPrimitive (disableAscii?: boolean): AnyJson {
|
|
203
|
+
return this.isNone
|
|
204
|
+
? null
|
|
205
|
+
: this.#raw.toPrimitive(disableAscii);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @description Returns the base runtime type name for this instance
|
|
210
|
+
*/
|
|
211
|
+
public toRawType (isBare?: boolean): string {
|
|
212
|
+
const wrapped = this.registry.getClassName(this.#Type) || new this.#Type(this.registry).toRawType();
|
|
213
|
+
|
|
214
|
+
return isBare
|
|
215
|
+
? wrapped
|
|
216
|
+
: `Option<${wrapped}>`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @description Returns the string representation of the value
|
|
221
|
+
*/
|
|
222
|
+
public toString (): string {
|
|
223
|
+
return this.#raw.toString();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @description Encodes the value as a Uint8Array as per the SCALE specifications
|
|
228
|
+
* @param isBare true when the value has none of the type-specific prefixes (internal)
|
|
229
|
+
*/
|
|
230
|
+
public toU8a (isBare?: boolean): Uint8Array {
|
|
231
|
+
if (isBare) {
|
|
232
|
+
return this.#raw.toU8a(true);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const u8a = new Uint8Array(this.encodedLength);
|
|
236
|
+
|
|
237
|
+
if (this.isSome) {
|
|
238
|
+
u8a.set([1]);
|
|
239
|
+
u8a.set(this.#raw.toU8a(), 1);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return u8a;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @description Returns the value that the Option represents (if available), throws if null
|
|
247
|
+
*/
|
|
248
|
+
public unwrap (): T {
|
|
249
|
+
if (this.isNone) {
|
|
250
|
+
throw new Error('Option: unwrapping a None value');
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return this.#raw;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* @description Returns the value that the Option represents (if available) or defaultValue if none
|
|
258
|
+
* @param defaultValue The value to return if the option isNone
|
|
259
|
+
*/
|
|
260
|
+
public unwrapOr<O> (defaultValue: O): T | O {
|
|
261
|
+
return this.isSome
|
|
262
|
+
? this.unwrap()
|
|
263
|
+
: defaultValue;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* @description Returns the value that the Option represents (if available) or defaultValue if none
|
|
268
|
+
* @param defaultValue The value to return if the option isNone
|
|
269
|
+
*/
|
|
270
|
+
public unwrapOrDefault (): T {
|
|
271
|
+
return this.isSome
|
|
272
|
+
? this.unwrap()
|
|
273
|
+
: new this.#Type(this.registry);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/types-codec authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { TypeRegistry } from '@pezkuwi/types';
|
|
7
|
+
import { Result, Text, u32 } from '@pezkuwi/types-codec';
|
|
8
|
+
import { hexToString } from '@pezkuwi/util';
|
|
9
|
+
|
|
10
|
+
describe('Result', (): void => {
|
|
11
|
+
const registry = new TypeRegistry();
|
|
12
|
+
const Type = Result.with({ Err: Text, Ok: u32 });
|
|
13
|
+
|
|
14
|
+
it('has a sane toRawType representation', (): void => {
|
|
15
|
+
expect(new Type(registry).toRawType()).toEqual('Result<u32,Text>');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('decodes from a u8a (success)', (): void => {
|
|
19
|
+
const result = new Type(registry, new Uint8Array([0, 1, 2, 3, 4]));
|
|
20
|
+
|
|
21
|
+
expect(result.isOk).toBe(true);
|
|
22
|
+
expect(result.asOk.toU8a()).toEqual(new Uint8Array([1, 2, 3, 4]));
|
|
23
|
+
expect(result.toHex()).toEqual('0x0001020304');
|
|
24
|
+
expect(result.toJSON()).toEqual({
|
|
25
|
+
ok: 0x04030201
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('decodes from a u8a (error)', (): void => {
|
|
30
|
+
const result = new Type(registry, new Uint8Array([1, 4 << 2, 100, 101, 102, 103]));
|
|
31
|
+
|
|
32
|
+
expect(result.isErr).toBe(true);
|
|
33
|
+
expect(result.asErr.toU8a()).toEqual(new Uint8Array([4 << 2, 100, 101, 102, 103]));
|
|
34
|
+
expect(result.toHex()).toEqual('0x011064656667');
|
|
35
|
+
expect(result.toJSON()).toEqual({
|
|
36
|
+
err: hexToString('0x64656667')
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('decodes from a JSON representation', (): void => {
|
|
41
|
+
const result = new Type(registry, { Err: 'error' });
|
|
42
|
+
|
|
43
|
+
expect(result.isErr).toBe(true);
|
|
44
|
+
expect(result.asErr.toString()).toEqual('error');
|
|
45
|
+
expect(result.toHex()).toEqual('0x01146572726f72');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('decodes reusing instanciated inputs', (): void => {
|
|
49
|
+
const foo = new Text(registry, 'bar');
|
|
50
|
+
|
|
51
|
+
expect(
|
|
52
|
+
new Result(
|
|
53
|
+
registry,
|
|
54
|
+
Text,
|
|
55
|
+
Text,
|
|
56
|
+
{ Ok: foo }
|
|
57
|
+
).asOk
|
|
58
|
+
).toBe(foo);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('returns a proper raw typedef rom a built-in', (): void => {
|
|
62
|
+
expect(registry.createType('DispatchResult').toRawType()).toEqual('Result<(),DispatchError>');
|
|
63
|
+
});
|
|
64
|
+
});
|