@solana/options 2.0.0-experimental.fcff844 → 2.0.0-experimental.fd64233
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 +153 -4
- package/dist/index.node.cjs +2 -0
- package/dist/types/index.d.ts +4 -4
- package/dist/types/option-codec.d.ts +1 -1
- package/dist/types/unwrap-option-recursively.d.ts +1 -1
- package/dist/types/unwrap-option.d.ts +1 -1
- package/package.json +8 -8
- package/dist/index.development.js +0 -247
- package/dist/index.development.js.map +0 -1
- package/dist/index.production.min.js +0 -21
package/README.md
CHANGED
|
@@ -16,10 +16,159 @@
|
|
|
16
16
|
|
|
17
17
|
This package allows us to manage and serialize Rust-like Option types in JavaScript. It can be used standalone, but it is also exported as part of the Solana JavaScript SDK [`@solana/web3.js@experimental`](https://github.com/solana-labs/solana-web3.js/tree/master/packages/library).
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
This package is also part of the [`@solana/codecs` package](https://github.com/solana-labs/solana-web3.js/tree/master/packages/codecs) which acts as an entry point for all codec packages as well as for their documentation.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
## Creating options
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
In Rust, we define optional values as an `Option<T>` type which can either be `Some(T)` or `None`. This is usually represented as `T | null` in the JavaScript world. The issue with this approach is it doesn't work with nested options. For instance, an `Option<Option<T>>` in Rust would become a `T | null | null` in JavaScript which is equivalent to `T | null`. That means, there is no way for us to represent the `Some(None)` value in JavaScript or any other nested option.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
To solve this issue, this library provides an `Option<T>` union type that works very similarly to the Rust `Option<T>` type. It is defined as follows:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
type Option<T> = Some<T> | None;
|
|
29
|
+
type Some<T> = { __option: 'Some'; value: T };
|
|
30
|
+
type None = { __option: 'None' };
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
To improve the developer experience, helper functions are available to help you create options. The type `T` of the option can either be inferred by TypeScript or explicitly provided.
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
// Create an option with a value.
|
|
37
|
+
some('Hello World');
|
|
38
|
+
some<number | string>(123);
|
|
39
|
+
|
|
40
|
+
// Create an empty option.
|
|
41
|
+
none();
|
|
42
|
+
none<number | string>();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Option helpers
|
|
46
|
+
|
|
47
|
+
This library also provides helper functions to help us identify and manage `Option` types.
|
|
48
|
+
|
|
49
|
+
For instance, you can use the `isSome` and `isNone` type guards to check whether a given `Option` is of the desired type.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
isSome(some('Hello World')); // true
|
|
53
|
+
isSome(none()); // false
|
|
54
|
+
|
|
55
|
+
isNone(some('Hello World')); // false
|
|
56
|
+
isNone(none()); // true
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If you are given a type `T | null`, you may also use the `wrapNullable` helper function to transform it into an `Option<T>` type.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
wrapNullable('Hello world'); // Some<string>
|
|
63
|
+
wrapNullable(null); // None
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Unwrapping options
|
|
67
|
+
|
|
68
|
+
Several helpers are available to help you unwrap your options and access their potential value. For instance, the `unwrapOption` function transforms an `Option<T>` type into `T` if the value exits and `null` otherwise.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
unwrapOption(some('Hello World')); // "Hello World"
|
|
72
|
+
unwrapOption(none()); // null
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
If `null` isn’t the value you want to use for `None` options, you may provide a custom fallback function as the second argument. Its return value will be assigned to `None` options.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
unwrapOption(some('Hello World'), () => 'Default'); // "Hello World"
|
|
79
|
+
unwrapOption(none(), () => 'Default'); // "Default"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Note that this `unwrapOption` function does not recursively unwrap nested options. You may use the `unwrapOptionRecursively` function for that purpose instead.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
unwrapOptionRecursively(some(some(some('Hello World')))); // "Hello World"
|
|
86
|
+
unwrapOptionRecursively(some(some(none<string>()))); // null
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The `unwrapOptionRecursively` function also walks any object and array it encounters and recursively unwraps any option it identifies in its journey without mutating any object or array.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
unwrapOptionRecursively({
|
|
93
|
+
a: 'hello',
|
|
94
|
+
b: none(),
|
|
95
|
+
c: [{ c1: some(42) }, { c2: none() }],
|
|
96
|
+
});
|
|
97
|
+
// { a: "hello", b: null, c: [{ c1: 42 }, { c2: null }] }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The `unwrapOptionRecursively` also accepts a fallback function as a second argument to provide custom values for `None` options.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
unwrapOptionRecursively(
|
|
104
|
+
{
|
|
105
|
+
a: 'hello',
|
|
106
|
+
b: none(),
|
|
107
|
+
c: [{ c1: some(42) }, { c2: none() }],
|
|
108
|
+
},
|
|
109
|
+
() => 'Default',
|
|
110
|
+
);
|
|
111
|
+
// { a: "hello", b: "Default", c: [{ c1: 42 }, { c2: "Default" }] }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Option codec
|
|
115
|
+
|
|
116
|
+
The `getOptionCodec` function behaves exactly the same as the [`getNullableCodec`](https://github.com/solana-labs/solana-web3.js/tree/master/packages/codecs-data-structures#nullable-codec) except that it encodes `Option<T>` types instead of `T | null` types.
|
|
117
|
+
|
|
118
|
+
Namely, it accepts a codec of type `T` and returns a codec of type `Option<T>`. It stores whether or not the item exists as a boolean prefix using a `u8` by default.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
getOptionCodec(getStringCodec()).encode(some('Hi'));
|
|
122
|
+
// 0x01020000004869
|
|
123
|
+
// | | └-- utf8 string content ("Hi").
|
|
124
|
+
// | └-- u32 string prefix (2 characters).
|
|
125
|
+
// └-- 1-byte prefix (Some).
|
|
126
|
+
|
|
127
|
+
getOptionCodec(getStringCodec()).encode(none());
|
|
128
|
+
// 0x00
|
|
129
|
+
// └-- 1-byte prefix (None).
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
You may provide a number codec as the `prefix` option of the `getOptionCodec` function to configure how to store the boolean prefix.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const u32OptionStringCodec = getOptionCodec(getStringCodec(), {
|
|
136
|
+
prefix: getU32Codec(),
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
u32OptionStringCodec.encode(some('Hi'));
|
|
140
|
+
// 0x01000000020000004869
|
|
141
|
+
// └------┘ 4-byte prefix (Some).
|
|
142
|
+
|
|
143
|
+
u32OptionStringCodec.encode(none());
|
|
144
|
+
// 0x00000000
|
|
145
|
+
// └------┘ 4-byte prefix (None).
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Additionally, if the item is a `FixedSizeCodec`, you may set the `fixed` option to `true` to also make the returned option codec a `FixedSizeCodec`. To do so, it will pad `null` values with zeroes to match the length of existing values.
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
const fixedOptionStringCodec = getOptionCodec(
|
|
152
|
+
getStringCodec({ size: 8 }), // Only works with fixed-size items.
|
|
153
|
+
{ fixed: true },
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
fixedOptionStringCodec.encode(some('Hi'));
|
|
157
|
+
// 0x014869000000000000
|
|
158
|
+
// | └-- 8-byte utf8 string content ("Hi").
|
|
159
|
+
// └-- 1-byte prefix (Some).
|
|
160
|
+
|
|
161
|
+
fixedOptionStringCodec.encode(none());
|
|
162
|
+
// 0x000000000000000000
|
|
163
|
+
// | └-- 8-byte of padding to make a fixed-size codec.
|
|
164
|
+
// └-- 1-byte prefix (None).
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Separate `getOptionEncoder` and `getOptionDecoder` functions are also available.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
const bytes = getOptionEncoder(getStringEncoder()).encode(some('Hi'));
|
|
171
|
+
const value = getOptionDecoder(getStringDecoder()).decode(bytes);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
To read more about the available codecs and how to use them, check out the documentation of the main [`@solana/codecs` package](https://github.com/solana-labs/solana-web3.js/tree/master/packages/codecs).
|
package/dist/index.node.cjs
CHANGED
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from './option';
|
|
2
|
-
export * from './option-codec';
|
|
3
|
-
export * from './unwrap-option';
|
|
4
|
-
export * from './unwrap-option-recursively';
|
|
1
|
+
export * from './option.js';
|
|
2
|
+
export * from './option-codec.js';
|
|
3
|
+
export * from './unwrap-option.js';
|
|
4
|
+
export * from './unwrap-option-recursively.js';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Codec, Decoder, Encoder, FixedSizeCodec, FixedSizeDecoder, FixedSizeEncoder, VariableSizeCodec, VariableSizeDecoder, VariableSizeEncoder } from '@solana/codecs-core';
|
|
2
2
|
import { FixedSizeNumberCodec, FixedSizeNumberDecoder, FixedSizeNumberEncoder, NumberCodec, NumberDecoder, NumberEncoder } from '@solana/codecs-numbers';
|
|
3
|
-
import { Option, OptionOrNullable } from './option';
|
|
3
|
+
import { Option, OptionOrNullable } from './option.js';
|
|
4
4
|
/** Defines the config for option codecs. */
|
|
5
5
|
export type OptionCodecConfig<TPrefix extends NumberCodec | NumberEncoder | NumberDecoder> = {
|
|
6
6
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/options",
|
|
3
|
-
"version": "2.0.0-experimental.
|
|
3
|
+
"version": "2.0.0-experimental.fd64233",
|
|
4
4
|
"description": "Managing and serializing Rust-like Option types in JavaScript",
|
|
5
5
|
"exports": {
|
|
6
6
|
"browser": {
|
|
@@ -49,14 +49,14 @@
|
|
|
49
49
|
"node": ">=17.4"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@solana/codecs-core": "2.0.0-experimental.
|
|
53
|
-
"@solana/codecs-numbers": "2.0.0-experimental.
|
|
52
|
+
"@solana/codecs-core": "2.0.0-experimental.fd64233",
|
|
53
|
+
"@solana/codecs-numbers": "2.0.0-experimental.fd64233"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@solana/eslint-config-solana": "^1.0.2",
|
|
57
57
|
"@swc/jest": "^0.2.29",
|
|
58
|
-
"@types/jest": "^29.5.
|
|
59
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
58
|
+
"@types/jest": "^29.5.11",
|
|
59
|
+
"@typescript-eslint/eslint-plugin": "^6.13.2",
|
|
60
60
|
"@typescript-eslint/parser": "^6.3.0",
|
|
61
61
|
"agadoo": "^3.0.0",
|
|
62
62
|
"eslint": "^8.45.0",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"tsup": "^8.0.1",
|
|
71
71
|
"typescript": "^5.2.2",
|
|
72
72
|
"version-from-git": "^1.1.1",
|
|
73
|
-
"test-config": "0.0.0",
|
|
74
73
|
"build-scripts": "0.0.0",
|
|
74
|
+
"test-config": "0.0.0",
|
|
75
75
|
"tsconfig": "0.0.0"
|
|
76
76
|
},
|
|
77
77
|
"bundlewatch": {
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
]
|
|
84
84
|
},
|
|
85
85
|
"scripts": {
|
|
86
|
-
"compile:js": "tsup --config build-scripts/tsup.config.
|
|
87
|
-
"compile:typedefs": "tsc -p ./tsconfig.declarations.json",
|
|
86
|
+
"compile:js": "tsup --config build-scripts/tsup.config.package.ts",
|
|
87
|
+
"compile:typedefs": "tsc -p ./tsconfig.declarations.json && node node_modules/build-scripts/add-js-extension-to-types.mjs",
|
|
88
88
|
"dev": "jest -c node_modules/test-config/jest-dev.config.ts --rootDir . --watch",
|
|
89
89
|
"publish-packages": "pnpm publish --tag experimental --access public --no-git-checks",
|
|
90
90
|
"style:fix": "pnpm eslint --fix src/* && pnpm prettier -w src/* package.json",
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
this.globalThis = this.globalThis || {};
|
|
2
|
-
this.globalThis.solanaWeb3 = (function (exports) {
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
// src/option.ts
|
|
6
|
-
var some = (value) => ({ __option: "Some", value });
|
|
7
|
-
var none = () => ({ __option: "None" });
|
|
8
|
-
var isOption = (input) => !!(input && typeof input === "object" && "__option" in input && (input.__option === "Some" && "value" in input || input.__option === "None"));
|
|
9
|
-
var isSome = (option) => option.__option === "Some";
|
|
10
|
-
var isNone = (option) => option.__option === "None";
|
|
11
|
-
|
|
12
|
-
// ../codecs-core/dist/index.browser.js
|
|
13
|
-
function assertByteArrayIsNotEmptyForCodec(codecDescription, bytes, offset = 0) {
|
|
14
|
-
if (bytes.length - offset <= 0) {
|
|
15
|
-
throw new Error(`Codec [${codecDescription}] cannot decode empty byte arrays.`);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
function assertByteArrayHasEnoughBytesForCodec(codecDescription, expected, bytes, offset = 0) {
|
|
19
|
-
const bytesLength = bytes.length - offset;
|
|
20
|
-
if (bytesLength < expected) {
|
|
21
|
-
throw new Error(`Codec [${codecDescription}] expected ${expected} bytes, got ${bytesLength}.`);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
function getEncodedSize(value, encoder) {
|
|
25
|
-
return "fixedSize" in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value);
|
|
26
|
-
}
|
|
27
|
-
function createEncoder(encoder) {
|
|
28
|
-
return Object.freeze({
|
|
29
|
-
...encoder,
|
|
30
|
-
encode: (value) => {
|
|
31
|
-
const bytes = new Uint8Array(getEncodedSize(value, encoder));
|
|
32
|
-
encoder.write(value, bytes, 0);
|
|
33
|
-
return bytes;
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
function createDecoder(decoder) {
|
|
38
|
-
return Object.freeze({
|
|
39
|
-
...decoder,
|
|
40
|
-
decode: (bytes, offset = 0) => decoder.read(bytes, offset)[0]
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
function isFixedSize(codec) {
|
|
44
|
-
return "fixedSize" in codec && typeof codec.fixedSize === "number";
|
|
45
|
-
}
|
|
46
|
-
function assertIsFixedSize(codec, message) {
|
|
47
|
-
if (!isFixedSize(codec)) {
|
|
48
|
-
throw new Error(message != null ? message : "Expected a fixed-size codec, got a variable-size one.");
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function combineCodec(encoder, decoder) {
|
|
52
|
-
if (isFixedSize(encoder) !== isFixedSize(decoder)) {
|
|
53
|
-
throw new Error(`Encoder and decoder must either both be fixed-size or variable-size.`);
|
|
54
|
-
}
|
|
55
|
-
if (isFixedSize(encoder) && isFixedSize(decoder) && encoder.fixedSize !== decoder.fixedSize) {
|
|
56
|
-
throw new Error(
|
|
57
|
-
`Encoder and decoder must have the same fixed size, got [${encoder.fixedSize}] and [${decoder.fixedSize}].`
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
if (!isFixedSize(encoder) && !isFixedSize(decoder) && encoder.maxSize !== decoder.maxSize) {
|
|
61
|
-
throw new Error(
|
|
62
|
-
`Encoder and decoder must have the same max size, got [${encoder.maxSize}] and [${decoder.maxSize}].`
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
return {
|
|
66
|
-
...decoder,
|
|
67
|
-
...encoder,
|
|
68
|
-
decode: decoder.decode,
|
|
69
|
-
encode: encoder.encode,
|
|
70
|
-
read: decoder.read,
|
|
71
|
-
write: encoder.write
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// ../codecs-numbers/dist/index.browser.js
|
|
76
|
-
function assertNumberIsBetweenForCodec(codecDescription, min, max, value) {
|
|
77
|
-
if (value < min || value > max) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
`Codec [${codecDescription}] expected number to be in the range [${min}, ${max}], got ${value}.`
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
function isLittleEndian(config) {
|
|
84
|
-
return (config == null ? void 0 : config.endian) === 1 ? false : true;
|
|
85
|
-
}
|
|
86
|
-
function numberEncoderFactory(input) {
|
|
87
|
-
return createEncoder({
|
|
88
|
-
fixedSize: input.size,
|
|
89
|
-
write(value, bytes, offset) {
|
|
90
|
-
if (input.range) {
|
|
91
|
-
assertNumberIsBetweenForCodec(input.name, input.range[0], input.range[1], value);
|
|
92
|
-
}
|
|
93
|
-
const arrayBuffer = new ArrayBuffer(input.size);
|
|
94
|
-
input.set(new DataView(arrayBuffer), value, isLittleEndian(input.config));
|
|
95
|
-
bytes.set(new Uint8Array(arrayBuffer), offset);
|
|
96
|
-
return offset + input.size;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
function numberDecoderFactory(input) {
|
|
101
|
-
return createDecoder({
|
|
102
|
-
fixedSize: input.size,
|
|
103
|
-
read(bytes, offset = 0) {
|
|
104
|
-
assertByteArrayIsNotEmptyForCodec(input.name, bytes, offset);
|
|
105
|
-
assertByteArrayHasEnoughBytesForCodec(input.name, input.size, bytes, offset);
|
|
106
|
-
const view = new DataView(toArrayBuffer(bytes, offset, input.size));
|
|
107
|
-
return [input.get(view, isLittleEndian(input.config)), offset + input.size];
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
function toArrayBuffer(bytes, offset, length) {
|
|
112
|
-
const bytesOffset = bytes.byteOffset + (offset != null ? offset : 0);
|
|
113
|
-
const bytesLength = length != null ? length : bytes.byteLength;
|
|
114
|
-
return bytes.buffer.slice(bytesOffset, bytesOffset + bytesLength);
|
|
115
|
-
}
|
|
116
|
-
var getU8Encoder = () => numberEncoderFactory({
|
|
117
|
-
name: "u8",
|
|
118
|
-
range: [0, Number("0xff")],
|
|
119
|
-
set: (view, value) => view.setUint8(0, value),
|
|
120
|
-
size: 1
|
|
121
|
-
});
|
|
122
|
-
var getU8Decoder = () => numberDecoderFactory({
|
|
123
|
-
get: (view) => view.getUint8(0),
|
|
124
|
-
name: "u8",
|
|
125
|
-
size: 1
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// src/unwrap-option.ts
|
|
129
|
-
function unwrapOption(option, fallback) {
|
|
130
|
-
if (isSome(option))
|
|
131
|
-
return option.value;
|
|
132
|
-
return fallback ? fallback() : null;
|
|
133
|
-
}
|
|
134
|
-
var wrapNullable = (nullable) => nullable !== null ? some(nullable) : none();
|
|
135
|
-
|
|
136
|
-
// src/option-codec.ts
|
|
137
|
-
function getOptionEncoder(item, config = {}) {
|
|
138
|
-
var _a, _b, _c;
|
|
139
|
-
const prefix = (_a = config.prefix) != null ? _a : getU8Encoder();
|
|
140
|
-
const fixed = (_b = config.fixed) != null ? _b : false;
|
|
141
|
-
const isZeroSizeItem = isFixedSize(item) && isFixedSize(prefix) && item.fixedSize === 0;
|
|
142
|
-
if (fixed || isZeroSizeItem) {
|
|
143
|
-
assertIsFixedSize(item, "Fixed options can only be used with fixed-size codecs.");
|
|
144
|
-
assertIsFixedSize(prefix, "Fixed options can only be used with fixed-size prefix.");
|
|
145
|
-
const fixedSize = prefix.fixedSize + item.fixedSize;
|
|
146
|
-
return createEncoder({
|
|
147
|
-
fixedSize,
|
|
148
|
-
write: (optionOrNullable, bytes, offset) => {
|
|
149
|
-
const option = isOption(optionOrNullable) ? optionOrNullable : wrapNullable(optionOrNullable);
|
|
150
|
-
const prefixOffset = prefix.write(Number(isSome(option)), bytes, offset);
|
|
151
|
-
if (isSome(option)) {
|
|
152
|
-
item.write(option.value, bytes, prefixOffset);
|
|
153
|
-
}
|
|
154
|
-
return offset + fixedSize;
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
return createEncoder({
|
|
159
|
-
getSizeFromValue: (optionOrNullable) => {
|
|
160
|
-
const option = isOption(optionOrNullable) ? optionOrNullable : wrapNullable(optionOrNullable);
|
|
161
|
-
return getEncodedSize(Number(isSome(option)), prefix) + (isSome(option) ? getEncodedSize(option.value, item) : 0);
|
|
162
|
-
},
|
|
163
|
-
maxSize: (_c = sumCodecSizes([prefix, item].map(getMaxSize))) != null ? _c : void 0,
|
|
164
|
-
write: (optionOrNullable, bytes, offset) => {
|
|
165
|
-
const option = isOption(optionOrNullable) ? optionOrNullable : wrapNullable(optionOrNullable);
|
|
166
|
-
offset = prefix.write(Number(isSome(option)), bytes, offset);
|
|
167
|
-
if (isSome(option)) {
|
|
168
|
-
offset = item.write(option.value, bytes, offset);
|
|
169
|
-
}
|
|
170
|
-
return offset;
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
function getOptionDecoder(item, config = {}) {
|
|
175
|
-
var _a, _b, _c;
|
|
176
|
-
const prefix = (_a = config.prefix) != null ? _a : getU8Decoder();
|
|
177
|
-
const fixed = (_b = config.fixed) != null ? _b : false;
|
|
178
|
-
let fixedSize = null;
|
|
179
|
-
const isZeroSizeItem = isFixedSize(item) && isFixedSize(prefix) && item.fixedSize === 0;
|
|
180
|
-
if (fixed || isZeroSizeItem) {
|
|
181
|
-
assertIsFixedSize(item, "Fixed options can only be used with fixed-size codecs.");
|
|
182
|
-
assertIsFixedSize(prefix, "Fixed options can only be used with fixed-size prefix.");
|
|
183
|
-
fixedSize = prefix.fixedSize + item.fixedSize;
|
|
184
|
-
}
|
|
185
|
-
return createDecoder({
|
|
186
|
-
...fixedSize === null ? { maxSize: (_c = sumCodecSizes([prefix, item].map(getMaxSize))) != null ? _c : void 0 } : { fixedSize },
|
|
187
|
-
read: (bytes, offset) => {
|
|
188
|
-
if (bytes.length - offset <= 0) {
|
|
189
|
-
return [none(), offset];
|
|
190
|
-
}
|
|
191
|
-
const [isSome2, prefixOffset] = prefix.read(bytes, offset);
|
|
192
|
-
if (isSome2 === 0) {
|
|
193
|
-
return [none(), fixedSize !== null ? offset + fixedSize : prefixOffset];
|
|
194
|
-
}
|
|
195
|
-
const [value, newOffset] = item.read(bytes, prefixOffset);
|
|
196
|
-
return [some(value), fixedSize !== null ? offset + fixedSize : newOffset];
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
function getOptionCodec(item, config = {}) {
|
|
201
|
-
return combineCodec(getOptionEncoder(item, config), getOptionDecoder(item, config));
|
|
202
|
-
}
|
|
203
|
-
function sumCodecSizes(sizes) {
|
|
204
|
-
return sizes.reduce((all, size) => all === null || size === null ? null : all + size, 0);
|
|
205
|
-
}
|
|
206
|
-
function getMaxSize(codec) {
|
|
207
|
-
var _a;
|
|
208
|
-
return isFixedSize(codec) ? codec.fixedSize : (_a = codec.maxSize) != null ? _a : null;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// src/unwrap-option-recursively.ts
|
|
212
|
-
function unwrapOptionRecursively(input, fallback) {
|
|
213
|
-
if (!input || ArrayBuffer.isView(input)) {
|
|
214
|
-
return input;
|
|
215
|
-
}
|
|
216
|
-
const next = (x) => fallback ? unwrapOptionRecursively(x, fallback) : unwrapOptionRecursively(x);
|
|
217
|
-
if (isOption(input)) {
|
|
218
|
-
if (isSome(input))
|
|
219
|
-
return next(input.value);
|
|
220
|
-
return fallback ? fallback() : null;
|
|
221
|
-
}
|
|
222
|
-
if (Array.isArray(input)) {
|
|
223
|
-
return input.map(next);
|
|
224
|
-
}
|
|
225
|
-
if (typeof input === "object") {
|
|
226
|
-
return Object.fromEntries(Object.entries(input).map(([k, v]) => [k, next(v)]));
|
|
227
|
-
}
|
|
228
|
-
return input;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
exports.getOptionCodec = getOptionCodec;
|
|
232
|
-
exports.getOptionDecoder = getOptionDecoder;
|
|
233
|
-
exports.getOptionEncoder = getOptionEncoder;
|
|
234
|
-
exports.isNone = isNone;
|
|
235
|
-
exports.isOption = isOption;
|
|
236
|
-
exports.isSome = isSome;
|
|
237
|
-
exports.none = none;
|
|
238
|
-
exports.some = some;
|
|
239
|
-
exports.unwrapOption = unwrapOption;
|
|
240
|
-
exports.unwrapOptionRecursively = unwrapOptionRecursively;
|
|
241
|
-
exports.wrapNullable = wrapNullable;
|
|
242
|
-
|
|
243
|
-
return exports;
|
|
244
|
-
|
|
245
|
-
})({});
|
|
246
|
-
//# sourceMappingURL=out.js.map
|
|
247
|
-
//# sourceMappingURL=index.development.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/option.ts","../../codecs-core/src/assertions.ts","../../codecs-core/src/codec.ts","../../codecs-core/src/combine-codec.ts","../../codecs-numbers/dist/index.browser.js","../src/unwrap-option.ts","../src/option-codec.ts","../src/unwrap-option-recursively.ts"],"names":["isSome"],"mappings":"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","sourcesContent":["/**\n * An implementation of the Rust Option type in JavaScript.\n * It can be one of the following:\n * - <code>{@link Some}<T></code>: Meaning there is a value of type T.\n * - <code>{@link None}</code>: Meaning there is no value.\n */\nexport type Option<T> = Some<T> | None;\n\n/**\n * Defines a looser type that can be used when serializing an {@link Option}.\n * This allows us to pass null or the Option value directly whilst still\n * supporting the Option type for use-cases that need more type safety.\n */\nexport type OptionOrNullable<T> = Option<T> | T | null;\n\n/**\n * Represents an option of type `T` that has a value.\n *\n * @see {@link Option}\n */\nexport type Some<T> = Readonly<{ __option: 'Some'; value: T }>;\n\n/**\n * Represents an option of type `T` that has no value.\n *\n * @see {@link Option}\n */\nexport type None = Readonly<{ __option: 'None' }>;\n\n/**\n * Creates a new {@link Option} of type `T` that has a value.\n *\n * @see {@link Option}\n */\nexport const some = <T>(value: T): Option<T> => ({ __option: 'Some', value });\n\n/**\n * Creates a new {@link Option} of type `T` that has no value.\n *\n * @see {@link Option}\n */\nexport const none = <T>(): Option<T> => ({ __option: 'None' });\n\n/**\n * Whether the given data is an {@link Option}.\n */\nexport const isOption = <T = unknown>(input: unknown): input is Option<T> =>\n !!(\n input &&\n typeof input === 'object' &&\n '__option' in input &&\n ((input.__option === 'Some' && 'value' in input) || input.__option === 'None')\n );\n\n/**\n * Whether the given {@link Option} is a {@link Some}.\n */\nexport const isSome = <T>(option: Option<T>): option is Some<T> => option.__option === 'Some';\n\n/**\n * Whether the given {@link Option} is a {@link None}.\n */\nexport const isNone = <T>(option: Option<T>): option is None => option.__option === 'None';\n","/**\n * Asserts that a given byte array is not empty.\n */\nexport function assertByteArrayIsNotEmptyForCodec(codecDescription: string, bytes: Uint8Array, offset = 0) {\n if (bytes.length - offset <= 0) {\n // TODO: Coded error.\n throw new Error(`Codec [${codecDescription}] cannot decode empty byte arrays.`);\n }\n}\n\n/**\n * Asserts that a given byte array has enough bytes to decode.\n */\nexport function assertByteArrayHasEnoughBytesForCodec(\n codecDescription: string,\n expected: number,\n bytes: Uint8Array,\n offset = 0,\n) {\n const bytesLength = bytes.length - offset;\n if (bytesLength < expected) {\n // TODO: Coded error.\n throw new Error(`Codec [${codecDescription}] expected ${expected} bytes, got ${bytesLength}.`);\n }\n}\n","/**\n * Defines an offset in bytes.\n */\nexport type Offset = number;\n\ntype BaseEncoder<TFrom> = {\n /** Encode the provided value and return the encoded bytes directly. */\n readonly encode: (value: TFrom) => Uint8Array;\n /**\n * Writes the encoded value into the provided byte array at the given offset.\n * Returns the offset of the next byte after the encoded value.\n */\n readonly write: (value: TFrom, bytes: Uint8Array, offset: Offset) => Offset;\n};\n\nexport type FixedSizeEncoder<TFrom, TSize extends number = number> = BaseEncoder<TFrom> & {\n /** The fixed size of the encoded value in bytes. */\n readonly fixedSize: TSize;\n};\n\nexport type VariableSizeEncoder<TFrom> = BaseEncoder<TFrom> & {\n /** The total size of the encoded value in bytes. */\n readonly getSizeFromValue: (value: TFrom) => number;\n /** The maximum size an encoded value can be in bytes, if applicable. */\n readonly maxSize?: number;\n};\n\n/**\n * An object that can encode a value to a `Uint8Array`.\n */\nexport type Encoder<TFrom> = FixedSizeEncoder<TFrom> | VariableSizeEncoder<TFrom>;\n\ntype BaseDecoder<TTo> = {\n /** Decodes the provided byte array at the given offset (or zero) and returns the value directly. */\n readonly decode: (bytes: Uint8Array, offset?: Offset) => TTo;\n /**\n * Reads the encoded value from the provided byte array at the given offset.\n * Returns the decoded value and the offset of the next byte after the encoded value.\n */\n readonly read: (bytes: Uint8Array, offset: Offset) => [TTo, Offset];\n};\n\nexport type FixedSizeDecoder<TTo, TSize extends number = number> = BaseDecoder<TTo> & {\n /** The fixed size of the encoded value in bytes. */\n readonly fixedSize: TSize;\n};\n\nexport type VariableSizeDecoder<TTo> = BaseDecoder<TTo> & {\n /** The maximum size an encoded value can be in bytes, if applicable. */\n readonly maxSize?: number;\n};\n\n/**\n * An object that can decode a value from a `Uint8Array`.\n */\nexport type Decoder<TTo> = FixedSizeDecoder<TTo> | VariableSizeDecoder<TTo>;\n\nexport type FixedSizeCodec<TFrom, TTo extends TFrom = TFrom, TSize extends number = number> = FixedSizeEncoder<\n TFrom,\n TSize\n> &\n FixedSizeDecoder<TTo, TSize>;\n\nexport type VariableSizeCodec<TFrom, TTo extends TFrom = TFrom> = VariableSizeEncoder<TFrom> & VariableSizeDecoder<TTo>;\n\n/**\n * An object that can encode and decode a value to and from a `Uint8Array`.\n * It supports encoding looser types than it decodes for convenience.\n * For example, a `bigint` encoder will always decode to a `bigint`\n * but can be used to encode a `number`.\n *\n * @typeParam TFrom - The type of the value to encode.\n * @typeParam TTo - The type of the decoded value. Defaults to `TFrom`.\n */\nexport type Codec<TFrom, TTo extends TFrom = TFrom> = FixedSizeCodec<TFrom, TTo> | VariableSizeCodec<TFrom, TTo>;\n\n/**\n * Get the encoded size of a given value in bytes.\n */\nexport function getEncodedSize<TFrom>(\n value: TFrom,\n encoder: { fixedSize: number } | { getSizeFromValue: (value: TFrom) => number },\n): number {\n return 'fixedSize' in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value);\n}\n\n/** Fills the missing `encode` function using the existing `write` function. */\nexport function createEncoder<TFrom, TSize extends number>(\n encoder: Omit<FixedSizeEncoder<TFrom, TSize>, 'encode'>,\n): FixedSizeEncoder<TFrom, TSize>;\nexport function createEncoder<TFrom>(encoder: Omit<VariableSizeEncoder<TFrom>, 'encode'>): VariableSizeEncoder<TFrom>;\nexport function createEncoder<TFrom>(\n encoder: Omit<FixedSizeEncoder<TFrom>, 'encode'> | Omit<VariableSizeEncoder<TFrom>, 'encode'>,\n): Encoder<TFrom>;\nexport function createEncoder<TFrom>(\n encoder: Omit<FixedSizeEncoder<TFrom>, 'encode'> | Omit<VariableSizeEncoder<TFrom>, 'encode'>,\n): Encoder<TFrom> {\n return Object.freeze({\n ...encoder,\n encode: value => {\n const bytes = new Uint8Array(getEncodedSize(value, encoder));\n encoder.write(value, bytes, 0);\n return bytes;\n },\n });\n}\n\n/** Fills the missing `decode` function using the existing `read` function. */\nexport function createDecoder<TTo, TSize extends number>(\n decoder: Omit<FixedSizeDecoder<TTo, TSize>, 'decode'>,\n): FixedSizeDecoder<TTo, TSize>;\nexport function createDecoder<TTo>(decoder: Omit<VariableSizeDecoder<TTo>, 'decode'>): VariableSizeDecoder<TTo>;\nexport function createDecoder<TTo>(\n decoder: Omit<FixedSizeDecoder<TTo>, 'decode'> | Omit<VariableSizeDecoder<TTo>, 'decode'>,\n): Decoder<TTo>;\nexport function createDecoder<TTo>(\n decoder: Omit<FixedSizeDecoder<TTo>, 'decode'> | Omit<VariableSizeDecoder<TTo>, 'decode'>,\n): Decoder<TTo> {\n return Object.freeze({\n ...decoder,\n decode: (bytes, offset = 0) => decoder.read(bytes, offset)[0],\n });\n}\n\n/** Fills the missing `encode` and `decode` function using the existing `write` and `read` functions. */\nexport function createCodec<TFrom, TTo extends TFrom = TFrom, TSize extends number = number>(\n codec: Omit<FixedSizeCodec<TFrom, TTo, TSize>, 'encode' | 'decode'>,\n): FixedSizeCodec<TFrom, TTo, TSize>;\nexport function createCodec<TFrom, TTo extends TFrom = TFrom>(\n codec: Omit<VariableSizeCodec<TFrom, TTo>, 'encode' | 'decode'>,\n): VariableSizeCodec<TFrom, TTo>;\nexport function createCodec<TFrom, TTo extends TFrom = TFrom>(\n codec:\n | Omit<FixedSizeCodec<TFrom, TTo>, 'encode' | 'decode'>\n | Omit<VariableSizeCodec<TFrom, TTo>, 'encode' | 'decode'>,\n): Codec<TFrom, TTo>;\nexport function createCodec<TFrom, TTo extends TFrom = TFrom>(\n codec:\n | Omit<FixedSizeCodec<TFrom, TTo>, 'encode' | 'decode'>\n | Omit<VariableSizeCodec<TFrom, TTo>, 'encode' | 'decode'>,\n): Codec<TFrom, TTo> {\n return Object.freeze({\n ...codec,\n decode: (bytes, offset = 0) => codec.read(bytes, offset)[0],\n encode: value => {\n const bytes = new Uint8Array(getEncodedSize(value, codec));\n codec.write(value, bytes, 0);\n return bytes;\n },\n });\n}\n\nexport function isFixedSize<TFrom, TSize extends number>(\n encoder: FixedSizeEncoder<TFrom, TSize> | VariableSizeEncoder<TFrom>,\n): encoder is FixedSizeEncoder<TFrom, TSize>;\nexport function isFixedSize<TTo, TSize extends number>(\n decoder: FixedSizeDecoder<TTo, TSize> | VariableSizeDecoder<TTo>,\n): decoder is FixedSizeDecoder<TTo, TSize>;\nexport function isFixedSize<TFrom, TTo extends TFrom, TSize extends number>(\n codec: FixedSizeCodec<TFrom, TTo, TSize> | VariableSizeCodec<TFrom, TTo>,\n): codec is FixedSizeCodec<TFrom, TTo, TSize>;\nexport function isFixedSize<TSize extends number>(\n codec: { fixedSize: TSize } | { maxSize?: number },\n): codec is { fixedSize: TSize };\nexport function isFixedSize(codec: { fixedSize: number } | { maxSize?: number }): codec is { fixedSize: number } {\n return 'fixedSize' in codec && typeof codec.fixedSize === 'number';\n}\n\nexport function assertIsFixedSize<TFrom, TSize extends number>(\n encoder: FixedSizeEncoder<TFrom, TSize> | VariableSizeEncoder<TFrom>,\n message?: string,\n): asserts encoder is FixedSizeEncoder<TFrom, TSize>;\nexport function assertIsFixedSize<TTo, TSize extends number>(\n decoder: FixedSizeDecoder<TTo, TSize> | VariableSizeDecoder<TTo>,\n message?: string,\n): asserts decoder is FixedSizeDecoder<TTo, TSize>;\nexport function assertIsFixedSize<TFrom, TTo extends TFrom, TSize extends number>(\n codec: FixedSizeCodec<TFrom, TTo, TSize> | VariableSizeCodec<TFrom, TTo>,\n message?: string,\n): asserts codec is FixedSizeCodec<TFrom, TTo, TSize>;\nexport function assertIsFixedSize<TSize extends number>(\n codec: { fixedSize: TSize } | { maxSize?: number },\n message?: string,\n): asserts codec is { fixedSize: TSize };\nexport function assertIsFixedSize(\n codec: { fixedSize: number } | { maxSize?: number },\n message?: string,\n): asserts codec is { fixedSize: number } {\n if (!isFixedSize(codec)) {\n // TODO: Coded error.\n throw new Error(message ?? 'Expected a fixed-size codec, got a variable-size one.');\n }\n}\n\nexport function isVariableSize<TFrom>(encoder: Encoder<TFrom>): encoder is VariableSizeEncoder<TFrom>;\nexport function isVariableSize<TTo>(decoder: Decoder<TTo>): decoder is VariableSizeDecoder<TTo>;\nexport function isVariableSize<TFrom, TTo extends TFrom>(\n codec: Codec<TFrom, TTo>,\n): codec is VariableSizeCodec<TFrom, TTo>;\nexport function isVariableSize(codec: { fixedSize: number } | { maxSize?: number }): codec is { maxSize?: number };\nexport function isVariableSize(codec: { fixedSize: number } | { maxSize?: number }): codec is { maxSize?: number } {\n return !isFixedSize(codec);\n}\n\nexport function assertIsVariableSize<T>(\n encoder: Encoder<T>,\n message?: string,\n): asserts encoder is VariableSizeEncoder<T>;\nexport function assertIsVariableSize<T>(\n decoder: Decoder<T>,\n message?: string,\n): asserts decoder is VariableSizeDecoder<T>;\nexport function assertIsVariableSize<TFrom, TTo extends TFrom>(\n codec: Codec<TFrom, TTo>,\n message?: string,\n): asserts codec is VariableSizeCodec<TFrom, TTo>;\nexport function assertIsVariableSize(\n codec: { fixedSize: number } | { maxSize?: number },\n message?: string,\n): asserts codec is { maxSize?: number };\nexport function assertIsVariableSize(\n codec: { fixedSize: number } | { maxSize?: number },\n message?: string,\n): asserts codec is { maxSize?: number } {\n if (!isVariableSize(codec)) {\n // TODO: Coded error.\n throw new Error(message ?? 'Expected a variable-size codec, got a fixed-size one.');\n }\n}\n","import {\n Codec,\n Decoder,\n Encoder,\n FixedSizeCodec,\n FixedSizeDecoder,\n FixedSizeEncoder,\n isFixedSize,\n VariableSizeCodec,\n VariableSizeDecoder,\n VariableSizeEncoder,\n} from './codec';\n\n/**\n * Combines an encoder and a decoder into a codec.\n * The encoder and decoder must have the same fixed size, max size and description.\n * If a description is provided, it will override the encoder and decoder descriptions.\n */\nexport function combineCodec<TFrom, TTo extends TFrom, TSize extends number>(\n encoder: FixedSizeEncoder<TFrom, TSize>,\n decoder: FixedSizeDecoder<TTo, TSize>,\n): FixedSizeCodec<TFrom, TTo, TSize>;\nexport function combineCodec<TFrom, TTo extends TFrom>(\n encoder: VariableSizeEncoder<TFrom>,\n decoder: VariableSizeDecoder<TTo>,\n): VariableSizeCodec<TFrom, TTo>;\nexport function combineCodec<TFrom, TTo extends TFrom>(\n encoder: Encoder<TFrom>,\n decoder: Decoder<TTo>,\n): Codec<TFrom, TTo>;\nexport function combineCodec<TFrom, TTo extends TFrom>(\n encoder: Encoder<TFrom>,\n decoder: Decoder<TTo>,\n): Codec<TFrom, TTo> {\n if (isFixedSize(encoder) !== isFixedSize(decoder)) {\n // TODO: Coded error.\n throw new Error(`Encoder and decoder must either both be fixed-size or variable-size.`);\n }\n\n if (isFixedSize(encoder) && isFixedSize(decoder) && encoder.fixedSize !== decoder.fixedSize) {\n // TODO: Coded error.\n throw new Error(\n `Encoder and decoder must have the same fixed size, got [${encoder.fixedSize}] and [${decoder.fixedSize}].`,\n );\n }\n\n if (!isFixedSize(encoder) && !isFixedSize(decoder) && encoder.maxSize !== decoder.maxSize) {\n // TODO: Coded error.\n throw new Error(\n `Encoder and decoder must have the same max size, got [${encoder.maxSize}] and [${decoder.maxSize}].`,\n );\n }\n\n return {\n ...decoder,\n ...encoder,\n decode: decoder.decode,\n encode: encoder.encode,\n read: decoder.read,\n write: encoder.write,\n };\n}\n","import { combineCodec, createEncoder, createDecoder, assertByteArrayIsNotEmptyForCodec, assertByteArrayHasEnoughBytesForCodec } from '@solana/codecs-core';\n\n// src/assertions.ts\nfunction assertNumberIsBetweenForCodec(codecDescription, min, max, value) {\n if (value < min || value > max) {\n throw new Error(\n `Codec [${codecDescription}] expected number to be in the range [${min}, ${max}], got ${value}.`\n );\n }\n}\n\n// src/common.ts\nvar Endian = /* @__PURE__ */ ((Endian2) => {\n Endian2[Endian2[\"LITTLE\"] = 0] = \"LITTLE\";\n Endian2[Endian2[\"BIG\"] = 1] = \"BIG\";\n return Endian2;\n})(Endian || {});\nfunction isLittleEndian(config) {\n return config?.endian === 1 /* BIG */ ? false : true;\n}\nfunction numberEncoderFactory(input) {\n return createEncoder({\n fixedSize: input.size,\n write(value, bytes, offset) {\n if (input.range) {\n assertNumberIsBetweenForCodec(input.name, input.range[0], input.range[1], value);\n }\n const arrayBuffer = new ArrayBuffer(input.size);\n input.set(new DataView(arrayBuffer), value, isLittleEndian(input.config));\n bytes.set(new Uint8Array(arrayBuffer), offset);\n return offset + input.size;\n }\n });\n}\nfunction numberDecoderFactory(input) {\n return createDecoder({\n fixedSize: input.size,\n read(bytes, offset = 0) {\n assertByteArrayIsNotEmptyForCodec(input.name, bytes, offset);\n assertByteArrayHasEnoughBytesForCodec(input.name, input.size, bytes, offset);\n const view = new DataView(toArrayBuffer(bytes, offset, input.size));\n return [input.get(view, isLittleEndian(input.config)), offset + input.size];\n }\n });\n}\nfunction toArrayBuffer(bytes, offset, length) {\n const bytesOffset = bytes.byteOffset + (offset ?? 0);\n const bytesLength = length ?? bytes.byteLength;\n return bytes.buffer.slice(bytesOffset, bytesOffset + bytesLength);\n}\n\n// src/f32.ts\nvar getF32Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"f32\",\n set: (view, value, le) => view.setFloat32(0, value, le),\n size: 4\n});\nvar getF32Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => view.getFloat32(0, le),\n name: \"f32\",\n size: 4\n});\nvar getF32Codec = (config = {}) => combineCodec(getF32Encoder(config), getF32Decoder(config));\nvar getF64Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"f64\",\n set: (view, value, le) => view.setFloat64(0, value, le),\n size: 8\n});\nvar getF64Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => view.getFloat64(0, le),\n name: \"f64\",\n size: 8\n});\nvar getF64Codec = (config = {}) => combineCodec(getF64Encoder(config), getF64Decoder(config));\nvar getI128Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"i128\",\n range: [-BigInt(\"0x7fffffffffffffffffffffffffffffff\") - 1n, BigInt(\"0x7fffffffffffffffffffffffffffffff\")],\n set: (view, value, le) => {\n const leftOffset = le ? 8 : 0;\n const rightOffset = le ? 0 : 8;\n const rightMask = 0xffffffffffffffffn;\n view.setBigInt64(leftOffset, BigInt(value) >> 64n, le);\n view.setBigUint64(rightOffset, BigInt(value) & rightMask, le);\n },\n size: 16\n});\nvar getI128Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => {\n const leftOffset = le ? 8 : 0;\n const rightOffset = le ? 0 : 8;\n const left = view.getBigInt64(leftOffset, le);\n const right = view.getBigUint64(rightOffset, le);\n return (left << 64n) + right;\n },\n name: \"i128\",\n size: 16\n});\nvar getI128Codec = (config = {}) => combineCodec(getI128Encoder(config), getI128Decoder(config));\nvar getI16Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"i16\",\n range: [-Number(\"0x7fff\") - 1, Number(\"0x7fff\")],\n set: (view, value, le) => view.setInt16(0, value, le),\n size: 2\n});\nvar getI16Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => view.getInt16(0, le),\n name: \"i16\",\n size: 2\n});\nvar getI16Codec = (config = {}) => combineCodec(getI16Encoder(config), getI16Decoder(config));\nvar getI32Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"i32\",\n range: [-Number(\"0x7fffffff\") - 1, Number(\"0x7fffffff\")],\n set: (view, value, le) => view.setInt32(0, value, le),\n size: 4\n});\nvar getI32Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => view.getInt32(0, le),\n name: \"i32\",\n size: 4\n});\nvar getI32Codec = (config = {}) => combineCodec(getI32Encoder(config), getI32Decoder(config));\nvar getI64Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"i64\",\n range: [-BigInt(\"0x7fffffffffffffff\") - 1n, BigInt(\"0x7fffffffffffffff\")],\n set: (view, value, le) => view.setBigInt64(0, BigInt(value), le),\n size: 8\n});\nvar getI64Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => view.getBigInt64(0, le),\n name: \"i64\",\n size: 8\n});\nvar getI64Codec = (config = {}) => combineCodec(getI64Encoder(config), getI64Decoder(config));\nvar getI8Encoder = () => numberEncoderFactory({\n name: \"i8\",\n range: [-Number(\"0x7f\") - 1, Number(\"0x7f\")],\n set: (view, value) => view.setInt8(0, value),\n size: 1\n});\nvar getI8Decoder = () => numberDecoderFactory({\n get: (view) => view.getInt8(0),\n name: \"i8\",\n size: 1\n});\nvar getI8Codec = () => combineCodec(getI8Encoder(), getI8Decoder());\nvar getShortU16Encoder = () => createEncoder({\n getSizeFromValue: (value) => {\n if (value <= 127)\n return 1;\n if (value <= 16383)\n return 2;\n return 3;\n },\n maxSize: 3,\n write: (value, bytes, offset) => {\n assertNumberIsBetweenForCodec(\"shortU16\", 0, 65535, value);\n const shortU16Bytes = [0];\n for (let ii = 0; ; ii += 1) {\n const alignedValue = value >> ii * 7;\n if (alignedValue === 0) {\n break;\n }\n const nextSevenBits = 127 & alignedValue;\n shortU16Bytes[ii] = nextSevenBits;\n if (ii > 0) {\n shortU16Bytes[ii - 1] |= 128;\n }\n }\n bytes.set(shortU16Bytes, offset);\n return offset + shortU16Bytes.length;\n }\n});\nvar getShortU16Decoder = () => createDecoder({\n maxSize: 3,\n read: (bytes, offset) => {\n let value = 0;\n let byteCount = 0;\n while (++byteCount) {\n const byteIndex = byteCount - 1;\n const currentByte = bytes[offset + byteIndex];\n const nextSevenBits = 127 & currentByte;\n value |= nextSevenBits << byteIndex * 7;\n if ((currentByte & 128) === 0) {\n break;\n }\n }\n return [value, offset + byteCount];\n }\n});\nvar getShortU16Codec = () => combineCodec(getShortU16Encoder(), getShortU16Decoder());\nvar getU128Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"u128\",\n range: [0, BigInt(\"0xffffffffffffffffffffffffffffffff\")],\n set: (view, value, le) => {\n const leftOffset = le ? 8 : 0;\n const rightOffset = le ? 0 : 8;\n const rightMask = 0xffffffffffffffffn;\n view.setBigUint64(leftOffset, BigInt(value) >> 64n, le);\n view.setBigUint64(rightOffset, BigInt(value) & rightMask, le);\n },\n size: 16\n});\nvar getU128Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => {\n const leftOffset = le ? 8 : 0;\n const rightOffset = le ? 0 : 8;\n const left = view.getBigUint64(leftOffset, le);\n const right = view.getBigUint64(rightOffset, le);\n return (left << 64n) + right;\n },\n name: \"u128\",\n size: 16\n});\nvar getU128Codec = (config = {}) => combineCodec(getU128Encoder(config), getU128Decoder(config));\nvar getU16Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"u16\",\n range: [0, Number(\"0xffff\")],\n set: (view, value, le) => view.setUint16(0, value, le),\n size: 2\n});\nvar getU16Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => view.getUint16(0, le),\n name: \"u16\",\n size: 2\n});\nvar getU16Codec = (config = {}) => combineCodec(getU16Encoder(config), getU16Decoder(config));\nvar getU32Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"u32\",\n range: [0, Number(\"0xffffffff\")],\n set: (view, value, le) => view.setUint32(0, value, le),\n size: 4\n});\nvar getU32Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => view.getUint32(0, le),\n name: \"u32\",\n size: 4\n});\nvar getU32Codec = (config = {}) => combineCodec(getU32Encoder(config), getU32Decoder(config));\nvar getU64Encoder = (config = {}) => numberEncoderFactory({\n config,\n name: \"u64\",\n range: [0, BigInt(\"0xffffffffffffffff\")],\n set: (view, value, le) => view.setBigUint64(0, BigInt(value), le),\n size: 8\n});\nvar getU64Decoder = (config = {}) => numberDecoderFactory({\n config,\n get: (view, le) => view.getBigUint64(0, le),\n name: \"u64\",\n size: 8\n});\nvar getU64Codec = (config = {}) => combineCodec(getU64Encoder(config), getU64Decoder(config));\nvar getU8Encoder = () => numberEncoderFactory({\n name: \"u8\",\n range: [0, Number(\"0xff\")],\n set: (view, value) => view.setUint8(0, value),\n size: 1\n});\nvar getU8Decoder = () => numberDecoderFactory({\n get: (view) => view.getUint8(0),\n name: \"u8\",\n size: 1\n});\nvar getU8Codec = () => combineCodec(getU8Encoder(), getU8Decoder());\n\nexport { Endian, assertNumberIsBetweenForCodec, getF32Codec, getF32Decoder, getF32Encoder, getF64Codec, getF64Decoder, getF64Encoder, getI128Codec, getI128Decoder, getI128Encoder, getI16Codec, getI16Decoder, getI16Encoder, getI32Codec, getI32Decoder, getI32Encoder, getI64Codec, getI64Decoder, getI64Encoder, getI8Codec, getI8Decoder, getI8Encoder, getShortU16Codec, getShortU16Decoder, getShortU16Encoder, getU128Codec, getU128Decoder, getU128Encoder, getU16Codec, getU16Decoder, getU16Encoder, getU32Codec, getU32Decoder, getU32Encoder, getU64Codec, getU64Decoder, getU64Encoder, getU8Codec, getU8Decoder, getU8Encoder };\n","import { isSome, none, Option, some } from './option';\n\n/**\n * Unwraps the value of an {@link Option} of type `T`\n * or returns a fallback value that defaults to `null`.\n */\nexport function unwrapOption<T>(option: Option<T>): T | null;\nexport function unwrapOption<T, U>(option: Option<T>, fallback: () => U): T | U;\nexport function unwrapOption<T, U = null>(option: Option<T>, fallback?: () => U): T | U {\n if (isSome(option)) return option.value;\n return fallback ? fallback() : (null as U);\n}\n\n/**\n * Wraps a nullable value into an {@link Option}.\n */\nexport const wrapNullable = <T>(nullable: T | null): Option<T> => (nullable !== null ? some(nullable) : none<T>());\n","import {\n assertIsFixedSize,\n Codec,\n combineCodec,\n createDecoder,\n createEncoder,\n Decoder,\n Encoder,\n FixedSizeCodec,\n FixedSizeDecoder,\n FixedSizeEncoder,\n getEncodedSize,\n isFixedSize,\n VariableSizeCodec,\n VariableSizeDecoder,\n VariableSizeEncoder,\n} from '@solana/codecs-core';\nimport {\n FixedSizeNumberCodec,\n FixedSizeNumberDecoder,\n FixedSizeNumberEncoder,\n getU8Decoder,\n getU8Encoder,\n NumberCodec,\n NumberDecoder,\n NumberEncoder,\n} from '@solana/codecs-numbers';\n\nimport { isOption, isSome, none, Option, OptionOrNullable, some } from './option';\nimport { wrapNullable } from './unwrap-option';\n\n/** Defines the config for option codecs. */\nexport type OptionCodecConfig<TPrefix extends NumberCodec | NumberEncoder | NumberDecoder> = {\n /**\n * The codec to use for the boolean prefix.\n * @defaultValue u8 prefix.\n */\n prefix?: TPrefix;\n\n /**\n * Whether the item codec should be of fixed size.\n *\n * When this is true, a `None` value will skip the bytes that would\n * have been used for the item. Note that this will only work if the\n * item codec is of fixed size.\n * @defaultValue `false`\n */\n fixed?: boolean;\n};\n\n/**\n * Creates a encoder for an optional value using `null` as the `None` value.\n *\n * @param item - The encoder to use for the value that may be present.\n * @param config - A set of config for the encoder.\n */\nexport function getOptionEncoder<TFrom>(\n item: FixedSizeEncoder<TFrom>,\n config: OptionCodecConfig<FixedSizeNumberEncoder> & { fixed: true },\n): FixedSizeEncoder<OptionOrNullable<TFrom>>;\nexport function getOptionEncoder<TFrom>(\n item: FixedSizeEncoder<TFrom, 0>,\n config?: OptionCodecConfig<FixedSizeNumberEncoder>,\n): FixedSizeEncoder<OptionOrNullable<TFrom>>;\nexport function getOptionEncoder<TFrom>(\n item: Encoder<TFrom>,\n config?: OptionCodecConfig<NumberEncoder> & { fixed?: false },\n): VariableSizeEncoder<OptionOrNullable<TFrom>>;\nexport function getOptionEncoder<TFrom>(\n item: Encoder<TFrom>,\n config: OptionCodecConfig<NumberEncoder> = {},\n): Encoder<OptionOrNullable<TFrom>> {\n const prefix = config.prefix ?? getU8Encoder();\n const fixed = config.fixed ?? false;\n\n const isZeroSizeItem = isFixedSize(item) && isFixedSize(prefix) && item.fixedSize === 0;\n if (fixed || isZeroSizeItem) {\n assertIsFixedSize(item, 'Fixed options can only be used with fixed-size codecs.');\n assertIsFixedSize(prefix, 'Fixed options can only be used with fixed-size prefix.');\n const fixedSize = prefix.fixedSize + item.fixedSize;\n return createEncoder({\n fixedSize,\n write: (optionOrNullable: OptionOrNullable<TFrom>, bytes, offset) => {\n const option = isOption<TFrom>(optionOrNullable) ? optionOrNullable : wrapNullable(optionOrNullable);\n const prefixOffset = prefix.write(Number(isSome(option)), bytes, offset);\n if (isSome(option)) {\n item.write(option.value, bytes, prefixOffset);\n }\n return offset + fixedSize;\n },\n });\n }\n\n return createEncoder({\n getSizeFromValue: (optionOrNullable: OptionOrNullable<TFrom>) => {\n const option = isOption<TFrom>(optionOrNullable) ? optionOrNullable : wrapNullable(optionOrNullable);\n return (\n getEncodedSize(Number(isSome(option)), prefix) +\n (isSome(option) ? getEncodedSize(option.value, item) : 0)\n );\n },\n maxSize: sumCodecSizes([prefix, item].map(getMaxSize)) ?? undefined,\n write: (optionOrNullable: OptionOrNullable<TFrom>, bytes, offset) => {\n const option = isOption<TFrom>(optionOrNullable) ? optionOrNullable : wrapNullable(optionOrNullable);\n offset = prefix.write(Number(isSome(option)), bytes, offset);\n if (isSome(option)) {\n offset = item.write(option.value, bytes, offset);\n }\n return offset;\n },\n });\n}\n\n/**\n * Creates a decoder for an optional value using `null` as the `None` value.\n *\n * @param item - The decoder to use for the value that may be present.\n * @param config - A set of config for the decoder.\n */\nexport function getOptionDecoder<TTo>(\n item: FixedSizeDecoder<TTo>,\n config: OptionCodecConfig<FixedSizeNumberDecoder> & { fixed: true },\n): FixedSizeDecoder<Option<TTo>>;\nexport function getOptionDecoder<TTo>(\n item: FixedSizeDecoder<TTo, 0>,\n config?: OptionCodecConfig<FixedSizeNumberDecoder>,\n): FixedSizeDecoder<Option<TTo>>;\nexport function getOptionDecoder<TTo>(\n item: Decoder<TTo>,\n config?: OptionCodecConfig<NumberDecoder> & { fixed?: false },\n): VariableSizeDecoder<Option<TTo>>;\nexport function getOptionDecoder<TTo>(\n item: Decoder<TTo>,\n config: OptionCodecConfig<NumberDecoder> = {},\n): Decoder<Option<TTo>> {\n const prefix = config.prefix ?? getU8Decoder();\n const fixed = config.fixed ?? false;\n\n let fixedSize: number | null = null;\n const isZeroSizeItem = isFixedSize(item) && isFixedSize(prefix) && item.fixedSize === 0;\n if (fixed || isZeroSizeItem) {\n assertIsFixedSize(item, 'Fixed options can only be used with fixed-size codecs.');\n assertIsFixedSize(prefix, 'Fixed options can only be used with fixed-size prefix.');\n fixedSize = prefix.fixedSize + item.fixedSize;\n }\n\n return createDecoder({\n ...(fixedSize === null\n ? { maxSize: sumCodecSizes([prefix, item].map(getMaxSize)) ?? undefined }\n : { fixedSize }),\n read: (bytes: Uint8Array, offset) => {\n if (bytes.length - offset <= 0) {\n return [none(), offset];\n }\n const [isSome, prefixOffset] = prefix.read(bytes, offset);\n if (isSome === 0) {\n return [none(), fixedSize !== null ? offset + fixedSize : prefixOffset];\n }\n const [value, newOffset] = item.read(bytes, prefixOffset);\n return [some(value), fixedSize !== null ? offset + fixedSize : newOffset];\n },\n });\n}\n\n/**\n * Creates a codec for an optional value using `null` as the `None` value.\n *\n * @param item - The codec to use for the value that may be present.\n * @param config - A set of config for the codec.\n */\nexport function getOptionCodec<TFrom, TTo extends TFrom = TFrom>(\n item: FixedSizeCodec<TFrom, TTo>,\n config: OptionCodecConfig<FixedSizeNumberCodec> & { fixed: true },\n): FixedSizeCodec<OptionOrNullable<TFrom>, Option<TTo>>;\nexport function getOptionCodec<TFrom, TTo extends TFrom = TFrom>(\n item: FixedSizeCodec<TFrom, TTo, 0>,\n config?: OptionCodecConfig<FixedSizeNumberCodec>,\n): FixedSizeCodec<OptionOrNullable<TFrom>, Option<TTo>>;\nexport function getOptionCodec<TFrom, TTo extends TFrom = TFrom>(\n item: Codec<TFrom, TTo>,\n config?: OptionCodecConfig<NumberCodec> & { fixed?: false },\n): VariableSizeCodec<OptionOrNullable<TFrom>, Option<TTo>>;\nexport function getOptionCodec<TFrom, TTo extends TFrom = TFrom>(\n item: Codec<TFrom, TTo>,\n config: OptionCodecConfig<NumberCodec> = {},\n): Codec<OptionOrNullable<TFrom>, Option<TTo>> {\n return combineCodec(getOptionEncoder<TFrom>(item, config as object), getOptionDecoder<TTo>(item, config as object));\n}\n\nfunction sumCodecSizes(sizes: (number | null)[]): number | null {\n return sizes.reduce((all, size) => (all === null || size === null ? null : all + size), 0 as number | null);\n}\n\nfunction getMaxSize(codec: { fixedSize: number } | { maxSize?: number }): number | null {\n return isFixedSize(codec) ? codec.fixedSize : codec.maxSize ?? null;\n}\n","import { isOption, isSome, None, Some } from './option';\n\n/**\n * Lists all types that should not be recursively unwrapped.\n *\n * @see {@link UnwrappedOption}\n */\ntype UnUnwrappables =\n | string\n | number\n | boolean\n | symbol\n | bigint\n | undefined\n | null\n | Uint8Array\n | Int8Array\n | Uint16Array\n | Int16Array\n | Uint32Array\n | Int32Array\n | Date;\n\n/**\n * A type that defines the recursive unwrapping of a type `T`\n * such that all nested {@link Option} types are unwrapped.\n *\n * For each nested {@link Option} type, if the option is a {@link Some},\n * it returns the type of its value, otherwise, it returns the provided\n * fallback type `U` which defaults to `null`.\n */\nexport type UnwrappedOption<T, U = null> = T extends Some<infer TValue>\n ? UnwrappedOption<TValue, U>\n : T extends None\n ? U\n : T extends UnUnwrappables\n ? T\n : T extends object\n ? { [key in keyof T]: UnwrappedOption<T[key], U> }\n : T extends Array<infer TItem>\n ? Array<UnwrappedOption<TItem, U>>\n : T;\n\n/**\n * Recursively go through a type `T` such that all\n * nested {@link Option} types are unwrapped.\n *\n * For each nested {@link Option} type, if the option is a {@link Some},\n * it returns its value, otherwise, it returns the provided fallback value\n * which defaults to `null`.\n */\nexport function unwrapOptionRecursively<T>(input: T): UnwrappedOption<T>;\nexport function unwrapOptionRecursively<T, U>(input: T, fallback: () => U): UnwrappedOption<T, U>;\nexport function unwrapOptionRecursively<T, U = null>(input: T, fallback?: () => U): UnwrappedOption<T, U> {\n // Types to bypass.\n if (!input || ArrayBuffer.isView(input)) {\n return input as UnwrappedOption<T, U>;\n }\n\n const next = <X>(x: X) =>\n (fallback ? unwrapOptionRecursively(x, fallback) : unwrapOptionRecursively(x)) as UnwrappedOption<X, U>;\n\n // Handle Option.\n if (isOption(input)) {\n if (isSome(input)) return next(input.value) as UnwrappedOption<T, U>;\n return (fallback ? fallback() : null) as UnwrappedOption<T, U>;\n }\n\n // Walk.\n if (Array.isArray(input)) {\n return input.map(next) as UnwrappedOption<T, U>;\n }\n if (typeof input === 'object') {\n return Object.fromEntries(Object.entries(input).map(([k, v]) => [k, next(v)])) as UnwrappedOption<T, U>;\n }\n return input as UnwrappedOption<T, U>;\n}\n"]}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
this.globalThis = this.globalThis || {};
|
|
2
|
-
this.globalThis.solanaWeb3 = (function (exports) {
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
var S=e=>({__option:"Some",value:e}),T=()=>({__option:"None"}),m=e=>!!(e&&typeof e=="object"&&"__option"in e&&(e.__option==="Some"&&"value"in e||e.__option==="None")),d=e=>e.__option==="Some",M=e=>e.__option==="None";function E(e,r,n=0){if(r.length-n<=0)throw new Error(`Codec [${e}] cannot decode empty byte arrays.`)}function v(e,r,n,t=0){let o=n.length-t;if(o<r)throw new Error(`Codec [${e}] expected ${r} bytes, got ${o}.`)}function F(e,r){return "fixedSize"in r?r.fixedSize:r.getSizeFromValue(e)}function l(e){return Object.freeze({...e,encode:r=>{let n=new Uint8Array(F(r,e));return e.write(r,n,0),n}})}function U(e){return Object.freeze({...e,decode:(r,n=0)=>e.read(r,n)[0]})}function c(e){return "fixedSize"in e&&typeof e.fixedSize=="number"}function z(e,r){if(!c(e))throw new Error(r!=null?r:"Expected a fixed-size codec, got a variable-size one.")}function w(e,r){if(c(e)!==c(r))throw new Error("Encoder and decoder must either both be fixed-size or variable-size.");if(c(e)&&c(r)&&e.fixedSize!==r.fixedSize)throw new Error(`Encoder and decoder must have the same fixed size, got [${e.fixedSize}] and [${r.fixedSize}].`);if(!c(e)&&!c(r)&&e.maxSize!==r.maxSize)throw new Error(`Encoder and decoder must have the same max size, got [${e.maxSize}] and [${r.maxSize}].`);return {...r,...e,decode:r.decode,encode:e.encode,read:r.read,write:e.write}}function _(e,r,n,t){if(t<r||t>n)throw new Error(`Codec [${e}] expected number to be in the range [${r}, ${n}], got ${t}.`)}function N(e){return (e==null?void 0:e.endian)!==1}function V(e){return l({fixedSize:e.size,write(r,n,t){e.range&&_(e.name,e.range[0],e.range[1],r);let o=new ArrayBuffer(e.size);return e.set(new DataView(o),r,N(e.config)),n.set(new Uint8Array(o),t),t+e.size}})}function $(e){return U({fixedSize:e.size,read(r,n=0){E(e.name,r,n),v(e.name,e.size,r,n);let t=new DataView(j(r,n,e.size));return [e.get(t,N(e.config)),n+e.size]}})}function j(e,r,n){let t=e.byteOffset+(r!=null?r:0),o=n!=null?n:e.byteLength;return e.buffer.slice(t,t+o)}var I=()=>V({name:"u8",range:[0,+"0xff"],set:(e,r)=>e.setUint8(0,r),size:1}),y=()=>$({get:e=>e.getUint8(0),name:"u8",size:1});function W(e,r){return d(e)?e.value:r?r():null}var C=e=>e!==null?S(e):T();function L(e,r={}){var O,x,g;let n=(O=r.prefix)!=null?O:I(),t=(x=r.fixed)!=null?x:!1,o=c(e)&&c(n)&&e.fixedSize===0;if(t||o){z(e,"Fixed options can only be used with fixed-size codecs."),z(n,"Fixed options can only be used with fixed-size prefix.");let a=n.fixedSize+e.fixedSize;return l({fixedSize:a,write:(i,f,s)=>{let u=m(i)?i:C(i),b=n.write(Number(d(u)),f,s);return d(u)&&e.write(u.value,f,b),s+a}})}return l({getSizeFromValue:a=>{let i=m(a)?a:C(a);return F(Number(d(i)),n)+(d(i)?F(i.value,e):0)},maxSize:(g=h([n,e].map(D)))!=null?g:void 0,write:(a,i,f)=>{let s=m(a)?a:C(a);return f=n.write(Number(d(s)),i,f),d(s)&&(f=e.write(s.value,i,f)),f}})}function k(e,r={}){var x,g,a;let n=(x=r.prefix)!=null?x:y(),t=(g=r.fixed)!=null?g:!1,o=null,O=c(e)&&c(n)&&e.fixedSize===0;return (t||O)&&(z(e,"Fixed options can only be used with fixed-size codecs."),z(n,"Fixed options can only be used with fixed-size prefix."),o=n.fixedSize+e.fixedSize),U({...o===null?{maxSize:(a=h([n,e].map(D)))!=null?a:void 0}:{fixedSize:o},read:(i,f)=>{if(i.length-f<=0)return [T(),f];let[s,u]=n.read(i,f);if(s===0)return [T(),o!==null?f+o:u];let[b,A]=e.read(i,u);return [S(b),o!==null?f+o:A]}})}function Ue(e,r={}){return w(L(e,r),k(e,r))}function h(e){return e.reduce((r,n)=>r===null||n===null?null:r+n,0)}function D(e){var r;return c(e)?e.fixedSize:(r=e.maxSize)!=null?r:null}function B(e,r){if(!e||ArrayBuffer.isView(e))return e;let n=t=>r?B(t,r):B(t);return m(e)?d(e)?n(e.value):r?r():null:Array.isArray(e)?e.map(n):typeof e=="object"?Object.fromEntries(Object.entries(e).map(([t,o])=>[t,n(o)])):e}
|
|
6
|
-
|
|
7
|
-
exports.getOptionCodec = Ue;
|
|
8
|
-
exports.getOptionDecoder = k;
|
|
9
|
-
exports.getOptionEncoder = L;
|
|
10
|
-
exports.isNone = M;
|
|
11
|
-
exports.isOption = m;
|
|
12
|
-
exports.isSome = d;
|
|
13
|
-
exports.none = T;
|
|
14
|
-
exports.some = S;
|
|
15
|
-
exports.unwrapOption = W;
|
|
16
|
-
exports.unwrapOptionRecursively = B;
|
|
17
|
-
exports.wrapNullable = C;
|
|
18
|
-
|
|
19
|
-
return exports;
|
|
20
|
-
|
|
21
|
-
})({});
|