@solana/codecs-data-structures 2.0.0-experimental.7ed772d → 2.0.0-experimental.803b2d8
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 +482 -4
- package/dist/index.browser.cjs +117 -63
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +118 -64
- package/dist/index.browser.js.map +1 -1
- package/dist/index.native.js +118 -64
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +117 -63
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +118 -64
- package/dist/index.node.js.map +1 -1
- package/dist/types/array.d.ts +3 -18
- package/dist/types/array.d.ts.map +1 -1
- package/dist/types/assertions.d.ts.map +1 -1
- package/dist/types/boolean.d.ts.map +1 -1
- package/dist/types/data-enum.d.ts +16 -18
- package/dist/types/data-enum.d.ts.map +1 -1
- package/dist/types/index.d.ts +13 -13
- package/dist/types/map.d.ts +4 -19
- package/dist/types/map.d.ts.map +1 -1
- package/dist/types/nullable.d.ts.map +1 -1
- package/dist/types/scalar-enum.d.ts +36 -17
- package/dist/types/scalar-enum.d.ts.map +1 -1
- package/dist/types/set.d.ts +4 -19
- package/dist/types/set.d.ts.map +1 -1
- package/dist/types/struct.d.ts +15 -30
- package/dist/types/struct.d.ts.map +1 -1
- package/package.json +13 -34
- package/dist/index.development.js +0 -800
- package/dist/index.development.js.map +0 -1
- package/dist/index.production.min.js +0 -47
package/dist/index.browser.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createEncoder, getEncodedSize, createDecoder, combineCodec, assertByteArrayHasEnoughBytesForCodec, assertIsFixedSize, mapEncoder, mapDecoder, fixEncoder, fixDecoder, assertByteArrayIsNotEmptyForCodec, isFixedSize } from '@solana/codecs-core';
|
|
2
2
|
import { getU32Encoder, getU32Decoder, getU8Encoder, getU8Decoder } from '@solana/codecs-numbers';
|
|
3
|
+
import { SolanaError, SOLANA_ERROR__CODECS_WRONG_NUMBER_OF_ITEMS, isSolanaError, SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH, SOLANA_ERROR__CODECS_CODEC_REQUIRES_FIXED_SIZE, SOLANA_ERROR__CODECS_ENUM_DISCRIMINATOR_OUT_OF_RANGE, SOLANA_ERROR__CODECS_INVALID_DATA_ENUM_VARIANT, SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_CODEC, SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_PREFIX, SOLANA_ERROR__CODECS_INVALID_SCALAR_ENUM_VARIANT } from '@solana/errors';
|
|
3
4
|
|
|
4
5
|
// src/array.ts
|
|
5
|
-
|
|
6
|
-
// src/assertions.ts
|
|
7
6
|
function assertValidNumberOfItemsForCodec(codecDescription, expected, actual) {
|
|
8
7
|
if (expected !== actual) {
|
|
9
|
-
throw new
|
|
8
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_WRONG_NUMBER_OF_ITEMS, {
|
|
9
|
+
actual,
|
|
10
|
+
codecDescription,
|
|
11
|
+
expected
|
|
12
|
+
});
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
15
|
function maxCodecSizes(sizes) {
|
|
@@ -28,9 +31,6 @@ function getMaxSize(codec) {
|
|
|
28
31
|
// src/array.ts
|
|
29
32
|
function getArrayEncoder(item, config = {}) {
|
|
30
33
|
const size = config.size ?? getU32Encoder();
|
|
31
|
-
if (size === "remainder") {
|
|
32
|
-
assertIsFixedSize(item, 'Codecs of "remainder" size must have fixed-size items.');
|
|
33
|
-
}
|
|
34
34
|
const fixedSize = computeArrayLikeCodecSize(size, getFixedSize(item));
|
|
35
35
|
const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? void 0;
|
|
36
36
|
return createEncoder({
|
|
@@ -57,9 +57,6 @@ function getArrayEncoder(item, config = {}) {
|
|
|
57
57
|
}
|
|
58
58
|
function getArrayDecoder(item, config = {}) {
|
|
59
59
|
const size = config.size ?? getU32Decoder();
|
|
60
|
-
if (size === "remainder") {
|
|
61
|
-
assertIsFixedSize(item, 'Codecs of "remainder" size must have fixed-size items.');
|
|
62
|
-
}
|
|
63
60
|
const itemSize = getFixedSize(item);
|
|
64
61
|
const fixedSize = computeArrayLikeCodecSize(size, itemSize);
|
|
65
62
|
const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? void 0;
|
|
@@ -70,7 +67,15 @@ function getArrayDecoder(item, config = {}) {
|
|
|
70
67
|
if (typeof size === "object" && bytes.slice(offset).length === 0) {
|
|
71
68
|
return [array, offset];
|
|
72
69
|
}
|
|
73
|
-
|
|
70
|
+
if (size === "remainder") {
|
|
71
|
+
while (offset < bytes.length) {
|
|
72
|
+
const [value, newOffset2] = item.read(bytes, offset);
|
|
73
|
+
offset = newOffset2;
|
|
74
|
+
array.push(value);
|
|
75
|
+
}
|
|
76
|
+
return [array, offset];
|
|
77
|
+
}
|
|
78
|
+
const [resolvedSize, newOffset] = typeof size === "number" ? [size, offset] : size.read(bytes, offset);
|
|
74
79
|
offset = newOffset;
|
|
75
80
|
for (let i = 0; i < resolvedSize; i += 1) {
|
|
76
81
|
const [value, newOffset2] = item.read(bytes, offset);
|
|
@@ -84,27 +89,6 @@ function getArrayDecoder(item, config = {}) {
|
|
|
84
89
|
function getArrayCodec(item, config = {}) {
|
|
85
90
|
return combineCodec(getArrayEncoder(item, config), getArrayDecoder(item, config));
|
|
86
91
|
}
|
|
87
|
-
function readArrayLikeCodecSize(size, itemSize, bytes, offset) {
|
|
88
|
-
if (typeof size === "number") {
|
|
89
|
-
return [size, offset];
|
|
90
|
-
}
|
|
91
|
-
if (typeof size === "object") {
|
|
92
|
-
return size.read(bytes, offset);
|
|
93
|
-
}
|
|
94
|
-
if (size === "remainder") {
|
|
95
|
-
if (itemSize === null) {
|
|
96
|
-
throw new Error('Codecs of "remainder" size must have fixed-size items.');
|
|
97
|
-
}
|
|
98
|
-
const remainder = Math.max(0, bytes.length - offset);
|
|
99
|
-
if (remainder % itemSize !== 0) {
|
|
100
|
-
throw new Error(
|
|
101
|
-
`The remainder of the byte array (${remainder} bytes) cannot be split into chunks of ${itemSize} bytes. Codecs of "remainder" size must have a remainder that is a multiple of its item size. In other words, ${remainder} modulo ${itemSize} should be equal to zero.`
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
return [remainder / itemSize, offset];
|
|
105
|
-
}
|
|
106
|
-
throw new Error(`Unrecognized array-like codec size: ${JSON.stringify(size)}`);
|
|
107
|
-
}
|
|
108
92
|
function computeArrayLikeCodecSize(size, itemSize) {
|
|
109
93
|
if (typeof size !== "number")
|
|
110
94
|
return null;
|
|
@@ -166,12 +150,32 @@ function getBitArrayCodec(size, config = {}) {
|
|
|
166
150
|
}
|
|
167
151
|
function getBooleanEncoder(config = {}) {
|
|
168
152
|
const size = config.size ?? getU8Encoder();
|
|
169
|
-
|
|
153
|
+
try {
|
|
154
|
+
assertIsFixedSize(size);
|
|
155
|
+
} catch (e) {
|
|
156
|
+
if (isSolanaError(e, SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
|
|
157
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_CODEC_REQUIRES_FIXED_SIZE, {
|
|
158
|
+
codecDescription: "bool"
|
|
159
|
+
});
|
|
160
|
+
} else {
|
|
161
|
+
throw e;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
170
164
|
return mapEncoder(size, (value) => value ? 1 : 0);
|
|
171
165
|
}
|
|
172
166
|
function getBooleanDecoder(config = {}) {
|
|
173
167
|
const size = config.size ?? getU8Decoder();
|
|
174
|
-
|
|
168
|
+
try {
|
|
169
|
+
assertIsFixedSize(size);
|
|
170
|
+
} catch (e) {
|
|
171
|
+
if (isSolanaError(e, SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
|
|
172
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_CODEC_REQUIRES_FIXED_SIZE, {
|
|
173
|
+
codecDescription: "bool"
|
|
174
|
+
});
|
|
175
|
+
} else {
|
|
176
|
+
throw e;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
175
179
|
return mapDecoder(size, (value) => Number(value) === 1);
|
|
176
180
|
}
|
|
177
181
|
function getBooleanCodec(config = {}) {
|
|
@@ -262,9 +266,11 @@ function getDataEnumDecoder(variants, config = {}) {
|
|
|
262
266
|
offset = dOffset;
|
|
263
267
|
const variantField = variants[Number(discriminator)] ?? null;
|
|
264
268
|
if (!variantField) {
|
|
265
|
-
throw new
|
|
266
|
-
|
|
267
|
-
|
|
269
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_ENUM_DISCRIMINATOR_OUT_OF_RANGE, {
|
|
270
|
+
discriminator,
|
|
271
|
+
maxRange: variants.length - 1,
|
|
272
|
+
minRange: 0
|
|
273
|
+
});
|
|
268
274
|
}
|
|
269
275
|
const [variant, vOffset] = variantField[1].read(bytes, offset);
|
|
270
276
|
offset = vOffset;
|
|
@@ -273,7 +279,10 @@ function getDataEnumDecoder(variants, config = {}) {
|
|
|
273
279
|
});
|
|
274
280
|
}
|
|
275
281
|
function getDataEnumCodec(variants, config = {}) {
|
|
276
|
-
return combineCodec(
|
|
282
|
+
return combineCodec(
|
|
283
|
+
getDataEnumEncoder(variants, config),
|
|
284
|
+
getDataEnumDecoder(variants, config)
|
|
285
|
+
);
|
|
277
286
|
}
|
|
278
287
|
function getDataEnumFixedSize(variants, prefix) {
|
|
279
288
|
if (variants.length === 0)
|
|
@@ -295,9 +304,10 @@ function getDataEnumMaxSize(variants, prefix) {
|
|
|
295
304
|
function getVariantDiscriminator(variants, variant) {
|
|
296
305
|
const discriminator = variants.findIndex(([key]) => variant.__kind === key);
|
|
297
306
|
if (discriminator < 0) {
|
|
298
|
-
throw new
|
|
299
|
-
|
|
300
|
-
|
|
307
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_INVALID_DATA_ENUM_VARIANT, {
|
|
308
|
+
value: variant.__kind,
|
|
309
|
+
variants: variants.map(([key]) => key)
|
|
310
|
+
});
|
|
301
311
|
}
|
|
302
312
|
return discriminator;
|
|
303
313
|
}
|
|
@@ -362,8 +372,24 @@ function getNullableEncoder(item, config = {}) {
|
|
|
362
372
|
const fixed = config.fixed ?? false;
|
|
363
373
|
const isZeroSizeItem = isFixedSize(item) && isFixedSize(prefix) && item.fixedSize === 0;
|
|
364
374
|
if (fixed || isZeroSizeItem) {
|
|
365
|
-
|
|
366
|
-
|
|
375
|
+
try {
|
|
376
|
+
assertIsFixedSize(item);
|
|
377
|
+
} catch (e) {
|
|
378
|
+
if (isSolanaError(e, SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
|
|
379
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_CODEC);
|
|
380
|
+
} else {
|
|
381
|
+
throw e;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
try {
|
|
385
|
+
assertIsFixedSize(prefix);
|
|
386
|
+
} catch (e) {
|
|
387
|
+
if (isSolanaError(e, SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
|
|
388
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_PREFIX);
|
|
389
|
+
} else {
|
|
390
|
+
throw e;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
367
393
|
const fixedSize = prefix.fixedSize + item.fixedSize;
|
|
368
394
|
return createEncoder({
|
|
369
395
|
fixedSize,
|
|
@@ -394,8 +420,24 @@ function getNullableDecoder(item, config = {}) {
|
|
|
394
420
|
let fixedSize = null;
|
|
395
421
|
const isZeroSizeItem = isFixedSize(item) && isFixedSize(prefix) && item.fixedSize === 0;
|
|
396
422
|
if (fixed || isZeroSizeItem) {
|
|
397
|
-
|
|
398
|
-
|
|
423
|
+
try {
|
|
424
|
+
assertIsFixedSize(item);
|
|
425
|
+
} catch (e) {
|
|
426
|
+
if (isSolanaError(e, SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
|
|
427
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_CODEC);
|
|
428
|
+
} else {
|
|
429
|
+
throw e;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
try {
|
|
433
|
+
assertIsFixedSize(prefix);
|
|
434
|
+
} catch (e) {
|
|
435
|
+
if (isSolanaError(e, SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
|
|
436
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_PREFIX);
|
|
437
|
+
} else {
|
|
438
|
+
throw e;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
399
441
|
fixedSize = prefix.fixedSize + item.fixedSize;
|
|
400
442
|
}
|
|
401
443
|
return createDecoder({
|
|
@@ -419,14 +461,17 @@ function getNullableCodec(item, config = {}) {
|
|
|
419
461
|
}
|
|
420
462
|
function getScalarEnumEncoder(constructor, config = {}) {
|
|
421
463
|
const prefix = config.size ?? getU8Encoder();
|
|
422
|
-
const { minRange, maxRange,
|
|
464
|
+
const { minRange, maxRange, allStringInputs, enumKeys, enumValues } = getScalarEnumStats(constructor);
|
|
423
465
|
return mapEncoder(prefix, (value) => {
|
|
424
466
|
const isInvalidNumber = typeof value === "number" && (value < minRange || value > maxRange);
|
|
425
|
-
const isInvalidString = typeof value === "string" && !
|
|
467
|
+
const isInvalidString = typeof value === "string" && !allStringInputs.includes(value);
|
|
426
468
|
if (isInvalidNumber || isInvalidString) {
|
|
427
|
-
throw new
|
|
428
|
-
|
|
429
|
-
|
|
469
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_INVALID_SCALAR_ENUM_VARIANT, {
|
|
470
|
+
maxRange,
|
|
471
|
+
minRange,
|
|
472
|
+
value,
|
|
473
|
+
variants: allStringInputs
|
|
474
|
+
});
|
|
430
475
|
}
|
|
431
476
|
if (typeof value === "number")
|
|
432
477
|
return value;
|
|
@@ -438,34 +483,40 @@ function getScalarEnumEncoder(constructor, config = {}) {
|
|
|
438
483
|
}
|
|
439
484
|
function getScalarEnumDecoder(constructor, config = {}) {
|
|
440
485
|
const prefix = config.size ?? getU8Decoder();
|
|
441
|
-
const { minRange, maxRange,
|
|
486
|
+
const { minRange, maxRange, enumKeys } = getScalarEnumStats(constructor);
|
|
442
487
|
return mapDecoder(prefix, (value) => {
|
|
443
488
|
const valueAsNumber = Number(value);
|
|
444
489
|
if (valueAsNumber < minRange || valueAsNumber > maxRange) {
|
|
445
|
-
throw new
|
|
446
|
-
|
|
447
|
-
|
|
490
|
+
throw new SolanaError(SOLANA_ERROR__CODECS_ENUM_DISCRIMINATOR_OUT_OF_RANGE, {
|
|
491
|
+
discriminator: valueAsNumber,
|
|
492
|
+
maxRange,
|
|
493
|
+
minRange
|
|
494
|
+
});
|
|
448
495
|
}
|
|
449
|
-
return
|
|
496
|
+
return constructor[enumKeys[valueAsNumber]];
|
|
450
497
|
});
|
|
451
498
|
}
|
|
452
499
|
function getScalarEnumCodec(constructor, config = {}) {
|
|
453
500
|
return combineCodec(getScalarEnumEncoder(constructor, config), getScalarEnumDecoder(constructor, config));
|
|
454
501
|
}
|
|
455
502
|
function getScalarEnumStats(constructor) {
|
|
456
|
-
const
|
|
457
|
-
const
|
|
458
|
-
|
|
503
|
+
const numericValues = Object.values(constructor).filter((v) => typeof v === "number");
|
|
504
|
+
const deduplicatedConstructor = Object.fromEntries(
|
|
505
|
+
Object.entries(constructor).slice(numericValues.length)
|
|
506
|
+
);
|
|
507
|
+
const enumKeys = Object.keys(deduplicatedConstructor);
|
|
508
|
+
const enumValues = Object.values(deduplicatedConstructor);
|
|
459
509
|
const minRange = 0;
|
|
460
|
-
const maxRange =
|
|
461
|
-
const
|
|
510
|
+
const maxRange = enumValues.length - 1;
|
|
511
|
+
const allStringInputs = [
|
|
512
|
+
.../* @__PURE__ */ new Set([...enumKeys, ...enumValues.filter((v) => typeof v === "string")])
|
|
513
|
+
];
|
|
462
514
|
return {
|
|
515
|
+
allStringInputs,
|
|
463
516
|
enumKeys,
|
|
464
517
|
enumValues,
|
|
465
|
-
isNumericEnum,
|
|
466
518
|
maxRange,
|
|
467
|
-
minRange
|
|
468
|
-
stringValues
|
|
519
|
+
minRange
|
|
469
520
|
};
|
|
470
521
|
}
|
|
471
522
|
function getSetEncoder(item, config = {}) {
|
|
@@ -512,7 +563,10 @@ function getStructDecoder(fields) {
|
|
|
512
563
|
});
|
|
513
564
|
}
|
|
514
565
|
function getStructCodec(fields) {
|
|
515
|
-
return combineCodec(
|
|
566
|
+
return combineCodec(
|
|
567
|
+
getStructEncoder(fields),
|
|
568
|
+
getStructDecoder(fields)
|
|
569
|
+
);
|
|
516
570
|
}
|
|
517
571
|
function getUnitEncoder() {
|
|
518
572
|
return createEncoder({
|