@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.
@@ -33,13 +33,15 @@ function getMaxSize(codec) {
33
33
  // src/array.ts
34
34
  function getArrayEncoder(item, config = {}) {
35
35
  const size = config.size ?? codecsNumbers.getU32Encoder();
36
+ assertValidSize(size);
36
37
  const fixedSize = computeArrayLikeCodecSize(size, getFixedSize(item));
37
38
  const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? void 0;
38
39
  return codecsCore.createEncoder({
39
40
  ...fixedSize !== null ? { fixedSize } : {
40
41
  getSizeFromValue: (array) => {
41
- const prefixSize = typeof size === "object" ? codecsCore.getEncodedSize(array.length, size) : 0;
42
- return prefixSize + [...array].reduce((all, value) => all + codecsCore.getEncodedSize(value, item), 0);
42
+ const prefixSize = isPrefixSize(size) ? codecsCore.getEncodedSize(array.length, size) : 0;
43
+ const suffixSize = isSentinelSize(size) && size.strategy !== "omitted" ? size.sentinel.length : 0;
44
+ return prefixSize + suffixSize + [...array].reduce((all, value) => all + codecsCore.getEncodedSize(value, item), 0);
43
45
  },
44
46
  maxSize
45
47
  },
@@ -47,18 +49,23 @@ function getArrayEncoder(item, config = {}) {
47
49
  if (typeof size === "number") {
48
50
  assertValidNumberOfItemsForCodec(config.description ?? "array", size, array.length);
49
51
  }
50
- if (typeof size === "object") {
52
+ if (isPrefixSize(size)) {
51
53
  offset = size.write(array.length, bytes, offset);
52
54
  }
53
55
  array.forEach((value) => {
54
56
  offset = item.write(value, bytes, offset);
55
57
  });
58
+ if (isSentinelSize(size) && size.strategy !== "omitted") {
59
+ bytes.set(size.sentinel, offset);
60
+ offset += size.sentinel.length;
61
+ }
56
62
  return offset;
57
63
  }
58
64
  });
59
65
  }
60
66
  function getArrayDecoder(item, config = {}) {
61
67
  const size = config.size ?? codecsNumbers.getU32Decoder();
68
+ assertValidSize(size);
62
69
  const itemSize = getFixedSize(item);
63
70
  const fixedSize = computeArrayLikeCodecSize(size, itemSize);
64
71
  const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? void 0;
@@ -66,7 +73,7 @@ function getArrayDecoder(item, config = {}) {
66
73
  ...fixedSize !== null ? { fixedSize } : { maxSize },
67
74
  read: (bytes, offset) => {
68
75
  const array = [];
69
- if (typeof size === "object" && !config.requireSizePrefix && offset >= bytes.length) {
76
+ if (isPrefixSize(size) && !config.requireSizePrefix && offset >= bytes.length) {
70
77
  return [array, offset];
71
78
  }
72
79
  if (size === "remainder") {
@@ -77,6 +84,29 @@ function getArrayDecoder(item, config = {}) {
77
84
  }
78
85
  return [array, offset];
79
86
  }
87
+ if (isSentinelSize(size)) {
88
+ const { sentinel, strategy = "required" } = size;
89
+ while (true) {
90
+ if (offset + sentinel.length > bytes.length) {
91
+ if (strategy === "required") {
92
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__SENTINEL_MISSING_AT_END_OF_BYTES, {
93
+ codecDescription: config.description ?? "array",
94
+ hexSentinel: hexBytes(sentinel),
95
+ sentinel
96
+ });
97
+ }
98
+ break;
99
+ }
100
+ if (codecsCore.containsBytes(bytes, sentinel, offset)) {
101
+ offset += sentinel.length;
102
+ break;
103
+ }
104
+ const [value, newOffset2] = item.read(bytes, offset);
105
+ offset = newOffset2;
106
+ array.push(value);
107
+ }
108
+ return [array, offset];
109
+ }
80
110
  const [resolvedSize, newOffset] = typeof size === "number" ? [size, offset] : size.read(bytes, offset);
81
111
  offset = newOffset;
82
112
  for (let i = 0; i < resolvedSize; i += 1) {
@@ -96,6 +126,20 @@ function computeArrayLikeCodecSize(size, itemSize) {
96
126
  if (size === 0) return 0;
97
127
  return itemSize === null ? null : itemSize * size;
98
128
  }
129
+ function isPrefixSize(size) {
130
+ return typeof size === "object" && size !== null && !isSentinelSize(size);
131
+ }
132
+ function isSentinelSize(size) {
133
+ return typeof size === "object" && size !== null && "__kind" in size && size.__kind === "sentinel";
134
+ }
135
+ function assertValidSize(size) {
136
+ if (isSentinelSize(size) && size.sentinel.length === 0) {
137
+ throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__SENTINEL_MUST_NOT_BE_EMPTY);
138
+ }
139
+ }
140
+ function hexBytes(bytes) {
141
+ return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
142
+ }
99
143
  function getBitArrayEncoder(size, config = {}) {
100
144
  const parsedConfig = typeof config === "boolean" ? { backward: config } : config;
101
145
  const backward = parsedConfig.backward ?? false;