@solana/codecs-data-structures 8.3.0 → 8.4.0-canary-20260918134912

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.
@@ -1,5 +1,71 @@
1
- import { Codec, Decoder, Encoder, FixedSizeCodec, FixedSizeDecoder, FixedSizeEncoder, VariableSizeCodec, VariableSizeDecoder, VariableSizeEncoder } from '@solana/codecs-core';
1
+ import { Codec, Decoder, Encoder, FixedSizeCodec, FixedSizeDecoder, FixedSizeEncoder, ReadonlyUint8Array, VariableSizeCodec, VariableSizeDecoder, VariableSizeEncoder } from '@solana/codecs-core';
2
2
  import { NumberCodec, NumberDecoder, NumberEncoder } from '@solana/codecs-numbers';
3
+ /**
4
+ * Defines whether the sentinel of a {@link ArrayLikeCodecSentinelSize} strategy is written when
5
+ * encoding and required when decoding.
6
+ *
7
+ * This mirrors the `sentinelCountStrategy` enumeration of Codama's `sentinelCountNode`.
8
+ *
9
+ * - `"required"` — The sentinel is written after the last item and must be present when decoding.
10
+ * Reaching the end of the byte array without it is an error. This is the default.
11
+ * - `"optional"` — The sentinel is written after the last item; when decoding, it is consumed if
12
+ * present but the collection may also end at the end of the byte array. Use this to tolerate
13
+ * tightly sized or legacy data that lacks the sentinel.
14
+ * - `"omitted"` — The sentinel is never written; when decoding, it is consumed if present and the
15
+ * collection also ends at the end of the byte array. Only meaningful when the collection is
16
+ * followed by unused space or the end of the byte array.
17
+ *
18
+ * Under `"optional"` and `"omitted"`, the sentinel must be no wider than the smallest possible item
19
+ * (see the constraints on {@link ArrayLikeCodecSentinelSize}).
20
+ *
21
+ * @see {@link ArrayLikeCodecSentinelSize}
22
+ */
23
+ export type SentinelCountStrategy = 'omitted' | 'optional' | 'required';
24
+ /**
25
+ * A size strategy for array-like codecs where the collection ends when the bytes at the next item
26
+ * position match a constant `sentinel`, compared at item boundaries only.
27
+ *
28
+ * Unlike {@link addCodecSentinel}, the sentinel is never searched for within an item's bytes, so its
29
+ * bytes may occur _inside_ an item without terminating the collection. This mirrors Codama's
30
+ * `sentinelCountNode`.
31
+ *
32
+ * @remarks
33
+ * Because the sentinel is only compared at the start of the next item slot, two invariants must hold
34
+ * for the collection to round-trip correctly. The codec does **not** enforce them — like Codama's
35
+ * `sentinelCountNode`, it is the caller's (or IDL author's) responsibility to guarantee them:
36
+ *
37
+ * 1. **No item may _begin_ with the sentinel's bytes.** A valid item that starts with the sentinel
38
+ * is indistinguishable from the terminator, so decoding would stop early at that item. The
39
+ * sentinel may still appear _inside_ an item, just never at its start. For instance, a single
40
+ * `0xff` byte is a poor sentinel for a list of public keys: roughly one key in 256 starts with
41
+ * `0xff`, so such a key would prematurely terminate the list. A sentinel as wide as an item — for
42
+ * instance the all-zero (default) public key — avoids this, since only that exact key can ever
43
+ * match the terminator.
44
+ * 2. **Under `"optional"` and `"omitted"`, the sentinel must be no wider than the smallest possible
45
+ * item.** Otherwise a trailing region shorter than the sentinel but large enough to hold a valid
46
+ * item would be skipped: decoding stops as soon as fewer bytes than the sentinel remain, so that
47
+ * final item would never be read. This cannot arise under `"required"` because a terminator is
48
+ * always written.
49
+ *
50
+ * @see {@link SentinelCountStrategy}
51
+ */
52
+ export type ArrayLikeCodecSentinelSize = {
53
+ /** Internal discriminator identifying this object as a sentinel size strategy. */
54
+ readonly __kind: 'sentinel';
55
+ /**
56
+ * The fixed-size constant compared against the bytes at each item position.
57
+ *
58
+ * No valid item may begin with these bytes, and under the `"optional"` / `"omitted"` strategies
59
+ * this must be no wider than the smallest possible item. See the remarks above.
60
+ */
61
+ readonly sentinel: ReadonlyUint8Array;
62
+ /**
63
+ * Whether the sentinel is written when encoding and required when decoding.
64
+ *
65
+ * @defaultValue `"required"`
66
+ */
67
+ readonly strategy?: SentinelCountStrategy;
68
+ };
3
69
  /**
4
70
  * Defines the possible size strategies for array-like codecs (`array`, `map`, and `set`).
5
71
  *
@@ -7,10 +73,12 @@ import { NumberCodec, NumberDecoder, NumberEncoder } from '@solana/codecs-number
7
73
  * - A {@link NumberCodec}, {@link NumberDecoder}, or {@link NumberEncoder} to store a size prefix.
8
74
  * - A fixed `number` of items, enforcing an exact length.
9
75
  * - The string `"remainder"`, which infers the number of items by consuming the rest of the available bytes.
76
+ * - An {@link ArrayLikeCodecSentinelSize} object, which ends the collection when the bytes at the next
77
+ * item position match a constant sentinel.
10
78
  *
11
79
  * @typeParam TPrefix - A number codec, decoder, or encoder used for size prefixing.
12
80
  */
13
- export type ArrayLikeCodecSize<TPrefix extends NumberCodec | NumberDecoder | NumberEncoder> = TPrefix | number | 'remainder';
81
+ export type ArrayLikeCodecSize<TPrefix extends NumberCodec | NumberDecoder | NumberEncoder> = ArrayLikeCodecSentinelSize | TPrefix | number | 'remainder';
14
82
  /**
15
83
  * Defines the configuration options for array codecs.
16
84
  *
@@ -40,6 +108,8 @@ export type ArrayCodecConfig<TPrefix extends NumberCodec | NumberDecoder | Numbe
40
108
  * - A {@link NumberCodec}, {@link NumberDecoder}, or {@link NumberEncoder} stores a size prefix before encoding the array.
41
109
  * - A `number` enforces a fixed number of elements.
42
110
  * - `"remainder"` uses all remaining bytes to infer the array length (only for fixed-size items).
111
+ * - An {@link ArrayLikeCodecSentinelSize} object ends the array when the bytes at the next item
112
+ * position match a constant sentinel.
43
113
  *
44
114
  * @defaultValue A `u32` size prefix.
45
115
  */
@@ -170,6 +240,18 @@ export declare function getArrayDecoder<TTo>(item: Decoder<TTo>, config?: ArrayC
170
240
  * ```
171
241
  *
172
242
  * @example
243
+ * Using a sentinel to mark the end of the array. Note that no valid item may begin with the
244
+ * sentinel's bytes, or decoding would stop early — see {@link ArrayLikeCodecSentinelSize} for the
245
+ * full constraints.
246
+ * ```ts
247
+ * const codec = getArrayCodec(getU8Codec(), { size: { __kind: 'sentinel', sentinel: new Uint8Array([0]) } });
248
+ * codec.encode([1, 2, 3]);
249
+ * // 0x01020300
250
+ * // | └-- The sentinel that marks the end of the array.
251
+ * // └-- 3 items of 1 byte each.
252
+ * ```
253
+ *
254
+ * @example
173
255
  * Requiring the size prefix to be present when decoding.
174
256
  * ```ts
175
257
  * getArrayCodec(getU8Codec()).decode(new Uint8Array([]));
@@ -184,6 +266,8 @@ export declare function getArrayDecoder<TTo>(item: Decoder<TTo>, config?: ArrayC
184
266
  * - A `Codec<number>` (e.g. `getU16Codec()`) stores a size prefix before the array.
185
267
  * - A `number` enforces a fixed number of elements.
186
268
  * - `"remainder"` uses all remaining bytes to infer the array length.
269
+ * - A sentinel object (see {@link ArrayLikeCodecSentinelSize}) ends the array when the bytes at the
270
+ * next item position match a constant sentinel.
187
271
  *
188
272
  * When the size is stored as a prefix, decoding an exhausted byte array yields an empty array,
189
273
  * which allows arrays to be appended to existing data layouts without breaking older data.
@@ -1 +1 @@
1
- {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/array.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/array.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import { ArrayLikeCodecSize } from './array';
10
10
  * - A fixed number of entries.
11
11
  * - `'remainder'`, which infers the number of entries based on the remaining bytes.
12
12
  * This option is only available for fixed-size keys and values.
13
+ * - An {@link ArrayLikeCodecSentinelSize} object, which ends the map when the bytes at the next entry position match a constant sentinel.
13
14
  *
14
15
  * @typeParam TPrefix - A number codec, encoder, or decoder used for the size prefix.
15
16
  */
@@ -1 +1 @@
1
- {"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/map.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/map.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import { ArrayLikeCodecSize } from './array';
10
10
  * - A {@link NumberCodec}, {@link NumberEncoder}, or {@link NumberDecoder} to store the size as a prefix.
11
11
  * - A fixed number of items, enforcing a strict length.
12
12
  * - The string `'remainder'` to infer the set size from the remaining bytes (only for fixed-size items).
13
+ * - An {@link ArrayLikeCodecSentinelSize} object to end the set when the bytes at the next item position match a constant sentinel.
13
14
  *
14
15
  * @typeParam TPrefix - The type used for encoding the size of the set.
15
16
  */
@@ -1 +1 @@
1
- {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../src/set.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../src/set.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana/codecs-data-structures",
3
- "version": "8.3.0",
3
+ "version": "8.4.0-canary-20260918134912",
4
4
  "description": "Codecs for various data structures",
5
5
  "homepage": "https://www.solanakit.com/api#solanacodecs-data-structures",
6
6
  "exports": {
@@ -56,9 +56,9 @@
56
56
  "maintained node versions"
57
57
  ],
58
58
  "dependencies": {
59
- "@solana/codecs-core": "8.3.0",
60
- "@solana/codecs-numbers": "8.3.0",
61
- "@solana/errors": "8.3.0"
59
+ "@solana/codecs-core": "8.4.0-canary-20260918134912",
60
+ "@solana/codecs-numbers": "8.4.0-canary-20260918134912",
61
+ "@solana/errors": "8.4.0-canary-20260918134912"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "typescript": ">=5.4.0"
package/src/array.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  Codec,
3
3
  combineCodec,
4
+ containsBytes,
4
5
  createDecoder,
5
6
  createEncoder,
6
7
  Decoder,
@@ -15,10 +16,83 @@ import {
15
16
  VariableSizeEncoder,
16
17
  } from '@solana/codecs-core';
17
18
  import { getU32Decoder, getU32Encoder, NumberCodec, NumberDecoder, NumberEncoder } from '@solana/codecs-numbers';
19
+ import {
20
+ SOLANA_ERROR__CODECS__SENTINEL_MISSING_AT_END_OF_BYTES,
21
+ SOLANA_ERROR__CODECS__SENTINEL_MUST_NOT_BE_EMPTY,
22
+ SolanaError,
23
+ } from '@solana/errors';
18
24
 
19
25
  import { assertValidNumberOfItemsForCodec } from './assertions';
20
26
  import { getFixedSize, getMaxSize } from './utils';
21
27
 
28
+ /**
29
+ * Defines whether the sentinel of a {@link ArrayLikeCodecSentinelSize} strategy is written when
30
+ * encoding and required when decoding.
31
+ *
32
+ * This mirrors the `sentinelCountStrategy` enumeration of Codama's `sentinelCountNode`.
33
+ *
34
+ * - `"required"` — The sentinel is written after the last item and must be present when decoding.
35
+ * Reaching the end of the byte array without it is an error. This is the default.
36
+ * - `"optional"` — The sentinel is written after the last item; when decoding, it is consumed if
37
+ * present but the collection may also end at the end of the byte array. Use this to tolerate
38
+ * tightly sized or legacy data that lacks the sentinel.
39
+ * - `"omitted"` — The sentinel is never written; when decoding, it is consumed if present and the
40
+ * collection also ends at the end of the byte array. Only meaningful when the collection is
41
+ * followed by unused space or the end of the byte array.
42
+ *
43
+ * Under `"optional"` and `"omitted"`, the sentinel must be no wider than the smallest possible item
44
+ * (see the constraints on {@link ArrayLikeCodecSentinelSize}).
45
+ *
46
+ * @see {@link ArrayLikeCodecSentinelSize}
47
+ */
48
+ export type SentinelCountStrategy = 'omitted' | 'optional' | 'required';
49
+
50
+ /**
51
+ * A size strategy for array-like codecs where the collection ends when the bytes at the next item
52
+ * position match a constant `sentinel`, compared at item boundaries only.
53
+ *
54
+ * Unlike {@link addCodecSentinel}, the sentinel is never searched for within an item's bytes, so its
55
+ * bytes may occur _inside_ an item without terminating the collection. This mirrors Codama's
56
+ * `sentinelCountNode`.
57
+ *
58
+ * @remarks
59
+ * Because the sentinel is only compared at the start of the next item slot, two invariants must hold
60
+ * for the collection to round-trip correctly. The codec does **not** enforce them — like Codama's
61
+ * `sentinelCountNode`, it is the caller's (or IDL author's) responsibility to guarantee them:
62
+ *
63
+ * 1. **No item may _begin_ with the sentinel's bytes.** A valid item that starts with the sentinel
64
+ * is indistinguishable from the terminator, so decoding would stop early at that item. The
65
+ * sentinel may still appear _inside_ an item, just never at its start. For instance, a single
66
+ * `0xff` byte is a poor sentinel for a list of public keys: roughly one key in 256 starts with
67
+ * `0xff`, so such a key would prematurely terminate the list. A sentinel as wide as an item — for
68
+ * instance the all-zero (default) public key — avoids this, since only that exact key can ever
69
+ * match the terminator.
70
+ * 2. **Under `"optional"` and `"omitted"`, the sentinel must be no wider than the smallest possible
71
+ * item.** Otherwise a trailing region shorter than the sentinel but large enough to hold a valid
72
+ * item would be skipped: decoding stops as soon as fewer bytes than the sentinel remain, so that
73
+ * final item would never be read. This cannot arise under `"required"` because a terminator is
74
+ * always written.
75
+ *
76
+ * @see {@link SentinelCountStrategy}
77
+ */
78
+ export type ArrayLikeCodecSentinelSize = {
79
+ /** Internal discriminator identifying this object as a sentinel size strategy. */
80
+ readonly __kind: 'sentinel';
81
+ /**
82
+ * The fixed-size constant compared against the bytes at each item position.
83
+ *
84
+ * No valid item may begin with these bytes, and under the `"optional"` / `"omitted"` strategies
85
+ * this must be no wider than the smallest possible item. See the remarks above.
86
+ */
87
+ readonly sentinel: ReadonlyUint8Array;
88
+ /**
89
+ * Whether the sentinel is written when encoding and required when decoding.
90
+ *
91
+ * @defaultValue `"required"`
92
+ */
93
+ readonly strategy?: SentinelCountStrategy;
94
+ };
95
+
22
96
  /**
23
97
  * Defines the possible size strategies for array-like codecs (`array`, `map`, and `set`).
24
98
  *
@@ -26,10 +100,13 @@ import { getFixedSize, getMaxSize } from './utils';
26
100
  * - A {@link NumberCodec}, {@link NumberDecoder}, or {@link NumberEncoder} to store a size prefix.
27
101
  * - A fixed `number` of items, enforcing an exact length.
28
102
  * - The string `"remainder"`, which infers the number of items by consuming the rest of the available bytes.
103
+ * - An {@link ArrayLikeCodecSentinelSize} object, which ends the collection when the bytes at the next
104
+ * item position match a constant sentinel.
29
105
  *
30
106
  * @typeParam TPrefix - A number codec, decoder, or encoder used for size prefixing.
31
107
  */
32
108
  export type ArrayLikeCodecSize<TPrefix extends NumberCodec | NumberDecoder | NumberEncoder> =
109
+ | ArrayLikeCodecSentinelSize
33
110
  | TPrefix
34
111
  | number
35
112
  | 'remainder';
@@ -63,6 +140,8 @@ export type ArrayCodecConfig<TPrefix extends NumberCodec | NumberDecoder | Numbe
63
140
  * - A {@link NumberCodec}, {@link NumberDecoder}, or {@link NumberEncoder} stores a size prefix before encoding the array.
64
141
  * - A `number` enforces a fixed number of elements.
65
142
  * - `"remainder"` uses all remaining bytes to infer the array length (only for fixed-size items).
143
+ * - An {@link ArrayLikeCodecSentinelSize} object ends the array when the bytes at the next item
144
+ * position match a constant sentinel.
66
145
  *
67
146
  * @defaultValue A `u32` size prefix.
68
147
  */
@@ -113,6 +192,7 @@ export function getArrayEncoder<TFrom>(
113
192
  config: ArrayCodecConfig<NumberEncoder> = {},
114
193
  ): Encoder<TFrom[]> {
115
194
  const size = config.size ?? getU32Encoder();
195
+ assertValidSize(size);
116
196
  const fixedSize = computeArrayLikeCodecSize(size, getFixedSize(item));
117
197
  const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? undefined;
118
198
 
@@ -121,8 +201,13 @@ export function getArrayEncoder<TFrom>(
121
201
  ? { fixedSize }
122
202
  : {
123
203
  getSizeFromValue: (array: TFrom[]) => {
124
- const prefixSize = typeof size === 'object' ? getEncodedSize(array.length, size) : 0;
125
- return prefixSize + [...array].reduce((all, value) => all + getEncodedSize(value, item), 0);
204
+ const prefixSize = isPrefixSize(size) ? getEncodedSize(array.length, size) : 0;
205
+ const suffixSize = isSentinelSize(size) && size.strategy !== 'omitted' ? size.sentinel.length : 0;
206
+ return (
207
+ prefixSize +
208
+ suffixSize +
209
+ [...array].reduce((all, value) => all + getEncodedSize(value, item), 0)
210
+ );
126
211
  },
127
212
  maxSize,
128
213
  }),
@@ -130,12 +215,16 @@ export function getArrayEncoder<TFrom>(
130
215
  if (typeof size === 'number') {
131
216
  assertValidNumberOfItemsForCodec(config.description ?? 'array', size, array.length);
132
217
  }
133
- if (typeof size === 'object') {
218
+ if (isPrefixSize(size)) {
134
219
  offset = size.write(array.length, bytes, offset);
135
220
  }
136
221
  array.forEach(value => {
137
222
  offset = item.write(value, bytes, offset);
138
223
  });
224
+ if (isSentinelSize(size) && size.strategy !== 'omitted') {
225
+ bytes.set(size.sentinel, offset);
226
+ offset += size.sentinel.length;
227
+ }
139
228
  return offset;
140
229
  },
141
230
  });
@@ -183,6 +272,7 @@ export function getArrayDecoder<TTo>(
183
272
  ): VariableSizeDecoder<TTo[]>;
184
273
  export function getArrayDecoder<TTo>(item: Decoder<TTo>, config: ArrayCodecConfig<NumberDecoder> = {}): Decoder<TTo[]> {
185
274
  const size = config.size ?? getU32Decoder();
275
+ assertValidSize(size);
186
276
  const itemSize = getFixedSize(item);
187
277
  const fixedSize = computeArrayLikeCodecSize(size, itemSize);
188
278
  const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? undefined;
@@ -191,7 +281,7 @@ export function getArrayDecoder<TTo>(item: Decoder<TTo>, config: ArrayCodecConfi
191
281
  ...(fixedSize !== null ? { fixedSize } : { maxSize }),
192
282
  read: (bytes: ReadonlyUint8Array | Uint8Array, offset) => {
193
283
  const array: TTo[] = [];
194
- if (typeof size === 'object' && !config.requireSizePrefix && offset >= bytes.length) {
284
+ if (isPrefixSize(size) && !config.requireSizePrefix && offset >= bytes.length) {
195
285
  return [array, offset];
196
286
  }
197
287
 
@@ -204,6 +294,32 @@ export function getArrayDecoder<TTo>(item: Decoder<TTo>, config: ArrayCodecConfi
204
294
  return [array, offset];
205
295
  }
206
296
 
297
+ if (isSentinelSize(size)) {
298
+ const { sentinel, strategy = 'required' } = size;
299
+ while (true) {
300
+ if (offset + sentinel.length > bytes.length) {
301
+ // Not enough bytes remain to hold the sentinel.
302
+ if (strategy === 'required') {
303
+ throw new SolanaError(SOLANA_ERROR__CODECS__SENTINEL_MISSING_AT_END_OF_BYTES, {
304
+ codecDescription: config.description ?? 'array',
305
+ hexSentinel: hexBytes(sentinel),
306
+ sentinel,
307
+ });
308
+ }
309
+ break;
310
+ }
311
+ if (containsBytes(bytes, sentinel, offset)) {
312
+ // The sentinel is present; consume it and stop.
313
+ offset += sentinel.length;
314
+ break;
315
+ }
316
+ const [value, newOffset] = item.read(bytes, offset);
317
+ offset = newOffset;
318
+ array.push(value);
319
+ }
320
+ return [array, offset];
321
+ }
322
+
207
323
  const [resolvedSize, newOffset] = typeof size === 'number' ? [size, offset] : size.read(bytes, offset);
208
324
  offset = newOffset;
209
325
  for (let i = 0; i < resolvedSize; i += 1) {
@@ -272,6 +388,18 @@ export function getArrayDecoder<TTo>(item: Decoder<TTo>, config: ArrayCodecConfi
272
388
  * ```
273
389
  *
274
390
  * @example
391
+ * Using a sentinel to mark the end of the array. Note that no valid item may begin with the
392
+ * sentinel's bytes, or decoding would stop early — see {@link ArrayLikeCodecSentinelSize} for the
393
+ * full constraints.
394
+ * ```ts
395
+ * const codec = getArrayCodec(getU8Codec(), { size: { __kind: 'sentinel', sentinel: new Uint8Array([0]) } });
396
+ * codec.encode([1, 2, 3]);
397
+ * // 0x01020300
398
+ * // | └-- The sentinel that marks the end of the array.
399
+ * // └-- 3 items of 1 byte each.
400
+ * ```
401
+ *
402
+ * @example
275
403
  * Requiring the size prefix to be present when decoding.
276
404
  * ```ts
277
405
  * getArrayCodec(getU8Codec()).decode(new Uint8Array([]));
@@ -286,6 +414,8 @@ export function getArrayDecoder<TTo>(item: Decoder<TTo>, config: ArrayCodecConfi
286
414
  * - A `Codec<number>` (e.g. `getU16Codec()`) stores a size prefix before the array.
287
415
  * - A `number` enforces a fixed number of elements.
288
416
  * - `"remainder"` uses all remaining bytes to infer the array length.
417
+ * - A sentinel object (see {@link ArrayLikeCodecSentinelSize}) ends the array when the bytes at the
418
+ * next item position match a constant sentinel.
289
419
  *
290
420
  * When the size is stored as a prefix, decoding an exhausted byte array yields an empty array,
291
421
  * which allows arrays to be appended to existing data layouts without breaking older data.
@@ -325,3 +455,24 @@ function computeArrayLikeCodecSize(size: number | object | 'remainder', itemSize
325
455
  if (size === 0) return 0;
326
456
  return itemSize === null ? null : itemSize * size;
327
457
  }
458
+
459
+ /** Narrows an array-like size to a numeric prefix codec, decoder, or encoder. */
460
+ function isPrefixSize(size: unknown): size is NumberCodec | NumberDecoder | NumberEncoder {
461
+ return typeof size === 'object' && size !== null && !isSentinelSize(size);
462
+ }
463
+
464
+ /** Narrows an array-like size to an {@link ArrayLikeCodecSentinelSize} object. */
465
+ function isSentinelSize(size: unknown): size is ArrayLikeCodecSentinelSize {
466
+ return typeof size === 'object' && size !== null && '__kind' in size && size.__kind === 'sentinel';
467
+ }
468
+
469
+ /** Throws if an array-like size strategy is misconfigured (e.g. a sentinel that can never be matched). */
470
+ function assertValidSize(size: number | object | 'remainder'): void {
471
+ if (isSentinelSize(size) && size.sentinel.length === 0) {
472
+ throw new SolanaError(SOLANA_ERROR__CODECS__SENTINEL_MUST_NOT_BE_EMPTY);
473
+ }
474
+ }
475
+
476
+ function hexBytes(bytes: ReadonlyUint8Array): string {
477
+ return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
478
+ }
package/src/map.ts CHANGED
@@ -26,6 +26,7 @@ import { getTupleDecoder, getTupleEncoder } from './tuple';
26
26
  * - A fixed number of entries.
27
27
  * - `'remainder'`, which infers the number of entries based on the remaining bytes.
28
28
  * This option is only available for fixed-size keys and values.
29
+ * - An {@link ArrayLikeCodecSentinelSize} object, which ends the map when the bytes at the next entry position match a constant sentinel.
29
30
  *
30
31
  * @typeParam TPrefix - A number codec, encoder, or decoder used for the size prefix.
31
32
  */
package/src/set.ts CHANGED
@@ -25,6 +25,7 @@ import { ArrayLikeCodecSize, getArrayDecoder, getArrayEncoder } from './array';
25
25
  * - A {@link NumberCodec}, {@link NumberEncoder}, or {@link NumberDecoder} to store the size as a prefix.
26
26
  * - A fixed number of items, enforcing a strict length.
27
27
  * - The string `'remainder'` to infer the set size from the remaining bytes (only for fixed-size items).
28
+ * - An {@link ArrayLikeCodecSentinelSize} object to end the set when the bytes at the next item position match a constant sentinel.
28
29
  *
29
30
  * @typeParam TPrefix - The type used for encoding the size of the set.
30
31
  */