@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.
@@ -2,13 +2,16 @@
2
2
 
3
3
  var codecsCore = require('@solana/codecs-core');
4
4
  var codecsNumbers = require('@solana/codecs-numbers');
5
+ var errors = require('@solana/errors');
5
6
 
6
7
  // src/array.ts
7
-
8
- // src/assertions.ts
9
8
  function assertValidNumberOfItemsForCodec(codecDescription, expected, actual) {
10
9
  if (expected !== actual) {
11
- throw new Error(`Expected [${codecDescription}] to have ${expected} items, got ${actual}.`);
10
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_WRONG_NUMBER_OF_ITEMS, {
11
+ actual,
12
+ codecDescription,
13
+ expected
14
+ });
12
15
  }
13
16
  }
14
17
  function maxCodecSizes(sizes) {
@@ -30,9 +33,6 @@ function getMaxSize(codec) {
30
33
  // src/array.ts
31
34
  function getArrayEncoder(item, config = {}) {
32
35
  const size = config.size ?? codecsNumbers.getU32Encoder();
33
- if (size === "remainder") {
34
- codecsCore.assertIsFixedSize(item, 'Codecs of "remainder" size must have fixed-size items.');
35
- }
36
36
  const fixedSize = computeArrayLikeCodecSize(size, getFixedSize(item));
37
37
  const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? void 0;
38
38
  return codecsCore.createEncoder({
@@ -59,9 +59,6 @@ function getArrayEncoder(item, config = {}) {
59
59
  }
60
60
  function getArrayDecoder(item, config = {}) {
61
61
  const size = config.size ?? codecsNumbers.getU32Decoder();
62
- if (size === "remainder") {
63
- codecsCore.assertIsFixedSize(item, 'Codecs of "remainder" size must have fixed-size items.');
64
- }
65
62
  const itemSize = getFixedSize(item);
66
63
  const fixedSize = computeArrayLikeCodecSize(size, itemSize);
67
64
  const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? void 0;
@@ -72,7 +69,15 @@ function getArrayDecoder(item, config = {}) {
72
69
  if (typeof size === "object" && bytes.slice(offset).length === 0) {
73
70
  return [array, offset];
74
71
  }
75
- const [resolvedSize, newOffset] = readArrayLikeCodecSize(size, itemSize, bytes, offset);
72
+ if (size === "remainder") {
73
+ while (offset < bytes.length) {
74
+ const [value, newOffset2] = item.read(bytes, offset);
75
+ offset = newOffset2;
76
+ array.push(value);
77
+ }
78
+ return [array, offset];
79
+ }
80
+ const [resolvedSize, newOffset] = typeof size === "number" ? [size, offset] : size.read(bytes, offset);
76
81
  offset = newOffset;
77
82
  for (let i = 0; i < resolvedSize; i += 1) {
78
83
  const [value, newOffset2] = item.read(bytes, offset);
@@ -86,27 +91,6 @@ function getArrayDecoder(item, config = {}) {
86
91
  function getArrayCodec(item, config = {}) {
87
92
  return codecsCore.combineCodec(getArrayEncoder(item, config), getArrayDecoder(item, config));
88
93
  }
89
- function readArrayLikeCodecSize(size, itemSize, bytes, offset) {
90
- if (typeof size === "number") {
91
- return [size, offset];
92
- }
93
- if (typeof size === "object") {
94
- return size.read(bytes, offset);
95
- }
96
- if (size === "remainder") {
97
- if (itemSize === null) {
98
- throw new Error('Codecs of "remainder" size must have fixed-size items.');
99
- }
100
- const remainder = Math.max(0, bytes.length - offset);
101
- if (remainder % itemSize !== 0) {
102
- throw new Error(
103
- `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.`
104
- );
105
- }
106
- return [remainder / itemSize, offset];
107
- }
108
- throw new Error(`Unrecognized array-like codec size: ${JSON.stringify(size)}`);
109
- }
110
94
  function computeArrayLikeCodecSize(size, itemSize) {
111
95
  if (typeof size !== "number")
112
96
  return null;
@@ -168,12 +152,32 @@ function getBitArrayCodec(size, config = {}) {
168
152
  }
169
153
  function getBooleanEncoder(config = {}) {
170
154
  const size = config.size ?? codecsNumbers.getU8Encoder();
171
- codecsCore.assertIsFixedSize(size, "Codec [bool] requires a fixed size.");
155
+ try {
156
+ codecsCore.assertIsFixedSize(size);
157
+ } catch (e) {
158
+ if (errors.isSolanaError(e, errors.SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
159
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_CODEC_REQUIRES_FIXED_SIZE, {
160
+ codecDescription: "bool"
161
+ });
162
+ } else {
163
+ throw e;
164
+ }
165
+ }
172
166
  return codecsCore.mapEncoder(size, (value) => value ? 1 : 0);
173
167
  }
174
168
  function getBooleanDecoder(config = {}) {
175
169
  const size = config.size ?? codecsNumbers.getU8Decoder();
176
- codecsCore.assertIsFixedSize(size, "Codec [bool] requires a fixed size.");
170
+ try {
171
+ codecsCore.assertIsFixedSize(size);
172
+ } catch (e) {
173
+ if (errors.isSolanaError(e, errors.SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
174
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_CODEC_REQUIRES_FIXED_SIZE, {
175
+ codecDescription: "bool"
176
+ });
177
+ } else {
178
+ throw e;
179
+ }
180
+ }
177
181
  return codecsCore.mapDecoder(size, (value) => Number(value) === 1);
178
182
  }
179
183
  function getBooleanCodec(config = {}) {
@@ -264,9 +268,11 @@ function getDataEnumDecoder(variants, config = {}) {
264
268
  offset = dOffset;
265
269
  const variantField = variants[Number(discriminator)] ?? null;
266
270
  if (!variantField) {
267
- throw new Error(
268
- `Enum discriminator out of range. Expected a number between 0 and ${variants.length - 1}, got ${discriminator}.`
269
- );
271
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_ENUM_DISCRIMINATOR_OUT_OF_RANGE, {
272
+ discriminator,
273
+ maxRange: variants.length - 1,
274
+ minRange: 0
275
+ });
270
276
  }
271
277
  const [variant, vOffset] = variantField[1].read(bytes, offset);
272
278
  offset = vOffset;
@@ -275,7 +281,10 @@ function getDataEnumDecoder(variants, config = {}) {
275
281
  });
276
282
  }
277
283
  function getDataEnumCodec(variants, config = {}) {
278
- return codecsCore.combineCodec(getDataEnumEncoder(variants, config), getDataEnumDecoder(variants, config));
284
+ return codecsCore.combineCodec(
285
+ getDataEnumEncoder(variants, config),
286
+ getDataEnumDecoder(variants, config)
287
+ );
279
288
  }
280
289
  function getDataEnumFixedSize(variants, prefix) {
281
290
  if (variants.length === 0)
@@ -297,9 +306,10 @@ function getDataEnumMaxSize(variants, prefix) {
297
306
  function getVariantDiscriminator(variants, variant) {
298
307
  const discriminator = variants.findIndex(([key]) => variant.__kind === key);
299
308
  if (discriminator < 0) {
300
- throw new Error(
301
- `Invalid data enum variant. Expected one of [${variants.map(([key]) => key).join(", ")}], got "${variant.__kind}".`
302
- );
309
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_INVALID_DATA_ENUM_VARIANT, {
310
+ value: variant.__kind,
311
+ variants: variants.map(([key]) => key)
312
+ });
303
313
  }
304
314
  return discriminator;
305
315
  }
@@ -364,8 +374,24 @@ function getNullableEncoder(item, config = {}) {
364
374
  const fixed = config.fixed ?? false;
365
375
  const isZeroSizeItem = codecsCore.isFixedSize(item) && codecsCore.isFixedSize(prefix) && item.fixedSize === 0;
366
376
  if (fixed || isZeroSizeItem) {
367
- codecsCore.assertIsFixedSize(item, "Fixed nullables can only be used with fixed-size codecs.");
368
- codecsCore.assertIsFixedSize(prefix, "Fixed nullables can only be used with fixed-size prefix.");
377
+ try {
378
+ codecsCore.assertIsFixedSize(item);
379
+ } catch (e) {
380
+ if (errors.isSolanaError(e, errors.SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
381
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_CODEC);
382
+ } else {
383
+ throw e;
384
+ }
385
+ }
386
+ try {
387
+ codecsCore.assertIsFixedSize(prefix);
388
+ } catch (e) {
389
+ if (errors.isSolanaError(e, errors.SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
390
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_PREFIX);
391
+ } else {
392
+ throw e;
393
+ }
394
+ }
369
395
  const fixedSize = prefix.fixedSize + item.fixedSize;
370
396
  return codecsCore.createEncoder({
371
397
  fixedSize,
@@ -396,8 +422,24 @@ function getNullableDecoder(item, config = {}) {
396
422
  let fixedSize = null;
397
423
  const isZeroSizeItem = codecsCore.isFixedSize(item) && codecsCore.isFixedSize(prefix) && item.fixedSize === 0;
398
424
  if (fixed || isZeroSizeItem) {
399
- codecsCore.assertIsFixedSize(item, "Fixed nullables can only be used with fixed-size codecs.");
400
- codecsCore.assertIsFixedSize(prefix, "Fixed nullables can only be used with fixed-size prefix.");
425
+ try {
426
+ codecsCore.assertIsFixedSize(item);
427
+ } catch (e) {
428
+ if (errors.isSolanaError(e, errors.SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
429
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_CODEC);
430
+ } else {
431
+ throw e;
432
+ }
433
+ }
434
+ try {
435
+ codecsCore.assertIsFixedSize(prefix);
436
+ } catch (e) {
437
+ if (errors.isSolanaError(e, errors.SOLANA_ERROR__CODECS_EXPECTED_FIXED_LENGTH_GOT_VARIABLE_LENGTH)) {
438
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_FIXED_NULLABLE_WITH_VARIABLE_SIZE_PREFIX);
439
+ } else {
440
+ throw e;
441
+ }
442
+ }
401
443
  fixedSize = prefix.fixedSize + item.fixedSize;
402
444
  }
403
445
  return codecsCore.createDecoder({
@@ -421,14 +463,17 @@ function getNullableCodec(item, config = {}) {
421
463
  }
422
464
  function getScalarEnumEncoder(constructor, config = {}) {
423
465
  const prefix = config.size ?? codecsNumbers.getU8Encoder();
424
- const { minRange, maxRange, stringValues, enumKeys, enumValues } = getScalarEnumStats(constructor);
466
+ const { minRange, maxRange, allStringInputs, enumKeys, enumValues } = getScalarEnumStats(constructor);
425
467
  return codecsCore.mapEncoder(prefix, (value) => {
426
468
  const isInvalidNumber = typeof value === "number" && (value < minRange || value > maxRange);
427
- const isInvalidString = typeof value === "string" && !stringValues.includes(value);
469
+ const isInvalidString = typeof value === "string" && !allStringInputs.includes(value);
428
470
  if (isInvalidNumber || isInvalidString) {
429
- throw new Error(
430
- `Invalid scalar enum variant. Expected one of [${stringValues.join(", ")}] or a number between ${minRange} and ${maxRange}, got "${value}".`
431
- );
471
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_INVALID_SCALAR_ENUM_VARIANT, {
472
+ maxRange,
473
+ minRange,
474
+ value,
475
+ variants: allStringInputs
476
+ });
432
477
  }
433
478
  if (typeof value === "number")
434
479
  return value;
@@ -440,34 +485,40 @@ function getScalarEnumEncoder(constructor, config = {}) {
440
485
  }
441
486
  function getScalarEnumDecoder(constructor, config = {}) {
442
487
  const prefix = config.size ?? codecsNumbers.getU8Decoder();
443
- const { minRange, maxRange, isNumericEnum, enumValues } = getScalarEnumStats(constructor);
488
+ const { minRange, maxRange, enumKeys } = getScalarEnumStats(constructor);
444
489
  return codecsCore.mapDecoder(prefix, (value) => {
445
490
  const valueAsNumber = Number(value);
446
491
  if (valueAsNumber < minRange || valueAsNumber > maxRange) {
447
- throw new Error(
448
- `Enum discriminator out of range. Expected a number between ${minRange} and ${maxRange}, got ${valueAsNumber}.`
449
- );
492
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS_ENUM_DISCRIMINATOR_OUT_OF_RANGE, {
493
+ discriminator: valueAsNumber,
494
+ maxRange,
495
+ minRange
496
+ });
450
497
  }
451
- return isNumericEnum ? valueAsNumber : enumValues[valueAsNumber];
498
+ return constructor[enumKeys[valueAsNumber]];
452
499
  });
453
500
  }
454
501
  function getScalarEnumCodec(constructor, config = {}) {
455
502
  return codecsCore.combineCodec(getScalarEnumEncoder(constructor, config), getScalarEnumDecoder(constructor, config));
456
503
  }
457
504
  function getScalarEnumStats(constructor) {
458
- const enumKeys = Object.keys(constructor);
459
- const enumValues = Object.values(constructor);
460
- const isNumericEnum = enumValues.some((v) => typeof v === "number");
505
+ const numericValues = Object.values(constructor).filter((v) => typeof v === "number");
506
+ const deduplicatedConstructor = Object.fromEntries(
507
+ Object.entries(constructor).slice(numericValues.length)
508
+ );
509
+ const enumKeys = Object.keys(deduplicatedConstructor);
510
+ const enumValues = Object.values(deduplicatedConstructor);
461
511
  const minRange = 0;
462
- const maxRange = isNumericEnum ? enumValues.length / 2 - 1 : enumValues.length - 1;
463
- const stringValues = isNumericEnum ? [...enumKeys] : [.../* @__PURE__ */ new Set([...enumKeys, ...enumValues])];
512
+ const maxRange = enumValues.length - 1;
513
+ const allStringInputs = [
514
+ .../* @__PURE__ */ new Set([...enumKeys, ...enumValues.filter((v) => typeof v === "string")])
515
+ ];
464
516
  return {
517
+ allStringInputs,
465
518
  enumKeys,
466
519
  enumValues,
467
- isNumericEnum,
468
520
  maxRange,
469
- minRange,
470
- stringValues
521
+ minRange
471
522
  };
472
523
  }
473
524
  function getSetEncoder(item, config = {}) {
@@ -514,7 +565,10 @@ function getStructDecoder(fields) {
514
565
  });
515
566
  }
516
567
  function getStructCodec(fields) {
517
- return codecsCore.combineCodec(getStructEncoder(fields), getStructDecoder(fields));
568
+ return codecsCore.combineCodec(
569
+ getStructEncoder(fields),
570
+ getStructDecoder(fields)
571
+ );
518
572
  }
519
573
  function getUnitEncoder() {
520
574
  return codecsCore.createEncoder({