@solana/codecs-data-structures 6.3.1 → 6.3.2-canary-20260313112147

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana/codecs-data-structures",
3
- "version": "6.3.1",
3
+ "version": "6.3.2-canary-20260313112147",
4
4
  "description": "Codecs for various data structures",
5
5
  "homepage": "https://www.solanakit.com/api#solanacodecs-data-structures",
6
6
  "exports": {
@@ -33,7 +33,8 @@
33
33
  "types": "./dist/types/index.d.ts",
34
34
  "type": "commonjs",
35
35
  "files": [
36
- "./dist/"
36
+ "./dist/",
37
+ "./src/"
37
38
  ],
38
39
  "sideEffects": false,
39
40
  "keywords": [
@@ -55,9 +56,9 @@
55
56
  "maintained node versions"
56
57
  ],
57
58
  "dependencies": {
58
- "@solana/errors": "6.3.1",
59
- "@solana/codecs-core": "6.3.1",
60
- "@solana/codecs-numbers": "6.3.1"
59
+ "@solana/codecs-core": "6.3.2-canary-20260313112147",
60
+ "@solana/codecs-numbers": "6.3.2-canary-20260313112147",
61
+ "@solana/errors": "6.3.2-canary-20260313112147"
61
62
  },
62
63
  "peerDependencies": {
63
64
  "typescript": "^5.0.0"
package/src/array.ts ADDED
@@ -0,0 +1,300 @@
1
+ import {
2
+ Codec,
3
+ combineCodec,
4
+ createDecoder,
5
+ createEncoder,
6
+ Decoder,
7
+ Encoder,
8
+ FixedSizeCodec,
9
+ FixedSizeDecoder,
10
+ FixedSizeEncoder,
11
+ getEncodedSize,
12
+ ReadonlyUint8Array,
13
+ VariableSizeCodec,
14
+ VariableSizeDecoder,
15
+ VariableSizeEncoder,
16
+ } from '@solana/codecs-core';
17
+ import { getU32Decoder, getU32Encoder, NumberCodec, NumberDecoder, NumberEncoder } from '@solana/codecs-numbers';
18
+
19
+ import { assertValidNumberOfItemsForCodec } from './assertions';
20
+ import { getFixedSize, getMaxSize } from './utils';
21
+
22
+ /**
23
+ * Defines the possible size strategies for array-like codecs (`array`, `map`, and `set`).
24
+ *
25
+ * The size of the collection can be determined using one of the following approaches:
26
+ * - A {@link NumberCodec}, {@link NumberDecoder}, or {@link NumberEncoder} to store a size prefix.
27
+ * - A fixed `number` of items, enforcing an exact length.
28
+ * - The string `"remainder"`, which infers the number of items by consuming the rest of the available bytes.
29
+ *
30
+ * @typeParam TPrefix - A number codec, decoder, or encoder used for size prefixing.
31
+ */
32
+ export type ArrayLikeCodecSize<TPrefix extends NumberCodec | NumberDecoder | NumberEncoder> =
33
+ | TPrefix
34
+ | number
35
+ | 'remainder';
36
+
37
+ /**
38
+ * Defines the configuration options for array codecs.
39
+ *
40
+ * @typeParam TPrefix - A number codec, decoder, or encoder used for size prefixing.
41
+ */
42
+ export type ArrayCodecConfig<TPrefix extends NumberCodec | NumberDecoder | NumberEncoder> = {
43
+ /**
44
+ * An optional description for the codec, that will be used in error messages.
45
+ */
46
+ description?: string;
47
+ /**
48
+ * Specifies how the size of the array is determined.
49
+ *
50
+ * - A {@link NumberCodec}, {@link NumberDecoder}, or {@link NumberEncoder} stores a size prefix before encoding the array.
51
+ * - A `number` enforces a fixed number of elements.
52
+ * - `"remainder"` uses all remaining bytes to infer the array length (only for fixed-size items).
53
+ *
54
+ * @defaultValue A `u32` size prefix.
55
+ */
56
+ size?: ArrayLikeCodecSize<TPrefix>;
57
+ };
58
+
59
+ /**
60
+ * Returns an encoder for arrays of values.
61
+ *
62
+ * This encoder serializes arrays by encoding each element using the provided item encoder.
63
+ * By default, a `u32` size prefix is included to indicate the number of items in the array.
64
+ * The `size` option can be used to modify this behaviour.
65
+ *
66
+ * For more details, see {@link getArrayCodec}.
67
+ *
68
+ * @typeParam TFrom - The type of the elements in the array.
69
+ *
70
+ * @param item - The encoder for each item in the array.
71
+ * @param config - Optional configuration for the size encoding strategy and description.
72
+ * @returns A `VariableSizeEncoder<TFrom[]>` for encoding arrays.
73
+ *
74
+ * @example
75
+ * Encoding an array of `u8` numbers.
76
+ * ```ts
77
+ * const encoder = getArrayEncoder(getU8Encoder());
78
+ * const bytes = encoder.encode([1, 2, 3]);
79
+ * // 0x03000000010203
80
+ * // | └-- 3 items of 1 byte each.
81
+ * // └-- 4-byte prefix telling us to read 3 items.
82
+ * ```
83
+ *
84
+ * @see {@link getArrayCodec}
85
+ */
86
+ export function getArrayEncoder<TFrom>(
87
+ item: Encoder<TFrom>,
88
+ config: ArrayCodecConfig<NumberEncoder> & { size: 0 },
89
+ ): FixedSizeEncoder<TFrom[], 0>;
90
+ export function getArrayEncoder<TFrom>(
91
+ item: FixedSizeEncoder<TFrom>,
92
+ config: ArrayCodecConfig<NumberEncoder> & { size: number },
93
+ ): FixedSizeEncoder<TFrom[]>;
94
+ export function getArrayEncoder<TFrom>(
95
+ item: Encoder<TFrom>,
96
+ config?: ArrayCodecConfig<NumberEncoder>,
97
+ ): VariableSizeEncoder<TFrom[]>;
98
+ export function getArrayEncoder<TFrom>(
99
+ item: Encoder<TFrom>,
100
+ config: ArrayCodecConfig<NumberEncoder> = {},
101
+ ): Encoder<TFrom[]> {
102
+ const size = config.size ?? getU32Encoder();
103
+ const fixedSize = computeArrayLikeCodecSize(size, getFixedSize(item));
104
+ const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? undefined;
105
+
106
+ return createEncoder({
107
+ ...(fixedSize !== null
108
+ ? { fixedSize }
109
+ : {
110
+ getSizeFromValue: (array: TFrom[]) => {
111
+ const prefixSize = typeof size === 'object' ? getEncodedSize(array.length, size) : 0;
112
+ return prefixSize + [...array].reduce((all, value) => all + getEncodedSize(value, item), 0);
113
+ },
114
+ maxSize,
115
+ }),
116
+ write: (array: TFrom[], bytes, offset) => {
117
+ if (typeof size === 'number') {
118
+ assertValidNumberOfItemsForCodec(config.description ?? 'array', size, array.length);
119
+ }
120
+ if (typeof size === 'object') {
121
+ offset = size.write(array.length, bytes, offset);
122
+ }
123
+ array.forEach(value => {
124
+ offset = item.write(value, bytes, offset);
125
+ });
126
+ return offset;
127
+ },
128
+ });
129
+ }
130
+
131
+ /**
132
+ * Returns a decoder for arrays of values.
133
+ *
134
+ * This decoder deserializes arrays by decoding each element using the provided item decoder.
135
+ * By default, a `u32` size prefix is expected to indicate the number of items in the array.
136
+ * The `size` option can be used to modify this behaviour.
137
+ *
138
+ * For more details, see {@link getArrayCodec}.
139
+ *
140
+ * @typeParam TTo - The type of the decoded elements in the array.
141
+ *
142
+ * @param item - The decoder for each item in the array.
143
+ * @param config - Optional configuration for the size decoding strategy.
144
+ * @returns A `VariableSizeDecoder<TTo[]>` for decoding arrays.
145
+ *
146
+ * @example
147
+ * Decoding an array of `u8` numbers.
148
+ * ```ts
149
+ * const decoder = getArrayDecoder(getU8Decoder());
150
+ * const array = decoder.decode(new Uint8Array([0x03, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03]));
151
+ * // [1, 2, 3]
152
+ * // 0x03000000010203
153
+ * // | └-- 3 items of 1 byte each.
154
+ * // └-- 4-byte prefix telling us to read 3 items.
155
+ * ```
156
+ *
157
+ * @see {@link getArrayCodec}
158
+ */
159
+ export function getArrayDecoder<TTo>(
160
+ item: Decoder<TTo>,
161
+ config: ArrayCodecConfig<NumberDecoder> & { size: 0 },
162
+ ): FixedSizeDecoder<TTo[], 0>;
163
+ export function getArrayDecoder<TTo>(
164
+ item: FixedSizeDecoder<TTo>,
165
+ config: ArrayCodecConfig<NumberDecoder> & { size: number },
166
+ ): FixedSizeDecoder<TTo[]>;
167
+ export function getArrayDecoder<TTo>(
168
+ item: Decoder<TTo>,
169
+ config?: ArrayCodecConfig<NumberDecoder>,
170
+ ): VariableSizeDecoder<TTo[]>;
171
+ export function getArrayDecoder<TTo>(item: Decoder<TTo>, config: ArrayCodecConfig<NumberDecoder> = {}): Decoder<TTo[]> {
172
+ const size = config.size ?? getU32Decoder();
173
+ const itemSize = getFixedSize(item);
174
+ const fixedSize = computeArrayLikeCodecSize(size, itemSize);
175
+ const maxSize = computeArrayLikeCodecSize(size, getMaxSize(item)) ?? undefined;
176
+
177
+ return createDecoder({
178
+ ...(fixedSize !== null ? { fixedSize } : { maxSize }),
179
+ read: (bytes: ReadonlyUint8Array | Uint8Array, offset) => {
180
+ const array: TTo[] = [];
181
+ if (typeof size === 'object' && bytes.slice(offset).length === 0) {
182
+ return [array, offset];
183
+ }
184
+
185
+ if (size === 'remainder') {
186
+ while (offset < bytes.length) {
187
+ const [value, newOffset] = item.read(bytes, offset);
188
+ offset = newOffset;
189
+ array.push(value);
190
+ }
191
+ return [array, offset];
192
+ }
193
+
194
+ const [resolvedSize, newOffset] = typeof size === 'number' ? [size, offset] : size.read(bytes, offset);
195
+ offset = newOffset;
196
+ for (let i = 0; i < resolvedSize; i += 1) {
197
+ const [value, newOffset] = item.read(bytes, offset);
198
+ offset = newOffset;
199
+ array.push(value);
200
+ }
201
+ return [array, offset];
202
+ },
203
+ });
204
+ }
205
+
206
+ /**
207
+ * Returns a codec for encoding and decoding arrays of values.
208
+ *
209
+ * This codec serializes arrays by encoding each element using the provided item codec.
210
+ * By default, a `u32` size prefix is included to indicate the number of items in the array.
211
+ * The `size` option can be used to modify this behaviour.
212
+ *
213
+ * @typeParam TFrom - The type of the elements to encode.
214
+ * @typeParam TTo - The type of the decoded elements.
215
+ *
216
+ * @param item - The codec for each item in the array.
217
+ * @param config - Optional configuration for the size encoding/decoding strategy.
218
+ * @returns A `VariableSizeCodec<TFrom[], TTo[]>` for encoding and decoding arrays.
219
+ *
220
+ * @example
221
+ * Encoding and decoding an array of `u8` numbers.
222
+ * ```ts
223
+ * const codec = getArrayCodec(getU8Codec());
224
+ * const bytes = codec.encode([1, 2, 3]);
225
+ * // 0x03000000010203
226
+ * // | └-- 3 items of 1 byte each.
227
+ * // └-- 4-byte prefix telling us to read 3 items.
228
+ *
229
+ * const array = codec.decode(bytes);
230
+ * // [1, 2, 3]
231
+ * ```
232
+ *
233
+ * @example
234
+ * Using a `u16` size prefix instead of `u32`.
235
+ * ```ts
236
+ * const codec = getArrayCodec(getU8Codec(), { size: getU16Codec() });
237
+ * const bytes = codec.encode([1, 2, 3]);
238
+ * // 0x0300010203
239
+ * // | └-- 3 items of 1 byte each.
240
+ * // └-- 2-byte prefix telling us to read 3 items.
241
+ * ```
242
+ *
243
+ * @example
244
+ * Using a fixed-size array of 3 items.
245
+ * ```ts
246
+ * const codec = getArrayCodec(getU8Codec(), { size: 3 });
247
+ * codec.encode([1, 2, 3]);
248
+ * // 0x010203
249
+ * // └-- 3 items of 1 byte each. There must always be 3 items in the array.
250
+ * ```
251
+ *
252
+ * @example
253
+ * Using the `"remainder"` size strategy.
254
+ * ```ts
255
+ * const codec = getArrayCodec(getU8Codec(), { size: 'remainder' });
256
+ * codec.encode([1, 2, 3]);
257
+ * // 0x010203
258
+ * // └-- 3 items of 1 byte each. The size is inferred from the remainder of the bytes.
259
+ * ```
260
+ *
261
+ * @remarks
262
+ * The size of the array can be controlled using the `size` option:
263
+ * - A `Codec<number>` (e.g. `getU16Codec()`) stores a size prefix before the array.
264
+ * - A `number` enforces a fixed number of elements.
265
+ * - `"remainder"` uses all remaining bytes to infer the array length.
266
+ *
267
+ * Separate {@link getArrayEncoder} and {@link getArrayDecoder} functions are available.
268
+ *
269
+ * ```ts
270
+ * const bytes = getArrayEncoder(getU8Encoder()).encode([1, 2, 3]);
271
+ * const array = getArrayDecoder(getU8Decoder()).decode(bytes);
272
+ * ```
273
+ *
274
+ * @see {@link getArrayEncoder}
275
+ * @see {@link getArrayDecoder}
276
+ */
277
+ export function getArrayCodec<TFrom, TTo extends TFrom = TFrom>(
278
+ item: Codec<TFrom, TTo>,
279
+ config: ArrayCodecConfig<NumberCodec> & { size: 0 },
280
+ ): FixedSizeCodec<TFrom[], TTo[], 0>;
281
+ export function getArrayCodec<TFrom, TTo extends TFrom = TFrom>(
282
+ item: FixedSizeCodec<TFrom, TTo>,
283
+ config: ArrayCodecConfig<NumberCodec> & { size: number },
284
+ ): FixedSizeCodec<TFrom[], TTo[]>;
285
+ export function getArrayCodec<TFrom, TTo extends TFrom = TFrom>(
286
+ item: Codec<TFrom, TTo>,
287
+ config?: ArrayCodecConfig<NumberCodec>,
288
+ ): VariableSizeCodec<TFrom[], TTo[]>;
289
+ export function getArrayCodec<TFrom, TTo extends TFrom = TFrom>(
290
+ item: Codec<TFrom, TTo>,
291
+ config: ArrayCodecConfig<NumberCodec> = {},
292
+ ): Codec<TFrom[], TTo[]> {
293
+ return combineCodec(getArrayEncoder(item, config as object), getArrayDecoder(item, config as object));
294
+ }
295
+
296
+ function computeArrayLikeCodecSize(size: number | object | 'remainder', itemSize: number | null): number | null {
297
+ if (typeof size !== 'number') return null;
298
+ if (size === 0) return 0;
299
+ return itemSize === null ? null : itemSize * size;
300
+ }
@@ -0,0 +1,16 @@
1
+ import { SOLANA_ERROR__CODECS__INVALID_NUMBER_OF_ITEMS, SolanaError } from '@solana/errors';
2
+
3
+ /** Checks the number of items in an array-like structure is expected. */
4
+ export function assertValidNumberOfItemsForCodec(
5
+ codecDescription: string,
6
+ expected: bigint | number,
7
+ actual: bigint | number,
8
+ ) {
9
+ if (expected !== actual) {
10
+ throw new SolanaError(SOLANA_ERROR__CODECS__INVALID_NUMBER_OF_ITEMS, {
11
+ actual,
12
+ codecDescription,
13
+ expected,
14
+ });
15
+ }
16
+ }
@@ -0,0 +1,203 @@
1
+ import {
2
+ assertByteArrayHasEnoughBytesForCodec,
3
+ combineCodec,
4
+ createDecoder,
5
+ createEncoder,
6
+ FixedSizeCodec,
7
+ FixedSizeDecoder,
8
+ FixedSizeEncoder,
9
+ } from '@solana/codecs-core';
10
+
11
+ /**
12
+ * Defines the configuration options for bit array codecs.
13
+ *
14
+ * A bit array codec encodes an array of booleans into bits, packing them into bytes.
15
+ * This configuration allows adjusting the bit ordering.
16
+ *
17
+ * @see {@link getBitArrayEncoder}
18
+ * @see {@link getBitArrayDecoder}
19
+ * @see {@link getBitArrayCodec}
20
+ */
21
+ export type BitArrayCodecConfig = {
22
+ /**
23
+ * Determines whether the bits should be read in reverse order.
24
+ *
25
+ * - `false` (default): The first boolean is stored in the most significant bit (MSB-first).
26
+ * - `true`: The first boolean is stored in the least significant bit (LSB-first).
27
+ *
28
+ * @defaultValue `false`
29
+ */
30
+ backward?: boolean;
31
+ };
32
+
33
+ /**
34
+ * Returns an encoder that packs an array of booleans into bits.
35
+ *
36
+ * This encoder converts a list of `boolean` values into a compact bit representation,
37
+ * storing 8 booleans per byte.
38
+ *
39
+ * The `backward` config option determines whether the bits are stored in MSB-first (`false`)
40
+ * or LSB-first (`true`).
41
+ *
42
+ * For more details, see {@link getBitArrayCodec}.
43
+ *
44
+ * @typeParam TSize - The number of bytes used to store the bit array.
45
+ *
46
+ * @param size - The number of bytes allocated for the bit array (must be sufficient for the expected boolean count).
47
+ * @param config - Configuration options for encoding the bit array.
48
+ * @returns A `FixedSizeEncoder<boolean[], TSize>` for encoding bit arrays.
49
+ *
50
+ * @example
51
+ * Encoding a bit array.
52
+ * ```ts
53
+ * const encoder = getBitArrayEncoder(1);
54
+ *
55
+ * encoder.encode([true, false, true, false, false, false, false, false]);
56
+ * // 0xa0 (0b10100000)
57
+ * ```
58
+ *
59
+ * @see {@link getBitArrayCodec}
60
+ */
61
+ export function getBitArrayEncoder<TSize extends number>(
62
+ size: TSize,
63
+ config: BitArrayCodecConfig | boolean = {},
64
+ ): FixedSizeEncoder<boolean[], TSize> {
65
+ const parsedConfig: BitArrayCodecConfig = typeof config === 'boolean' ? { backward: config } : config;
66
+ const backward = parsedConfig.backward ?? false;
67
+ return createEncoder({
68
+ fixedSize: size,
69
+ write(value: boolean[], bytes, offset) {
70
+ const bytesToAdd: number[] = [];
71
+
72
+ for (let i = 0; i < size; i += 1) {
73
+ let byte = 0;
74
+ for (let j = 0; j < 8; j += 1) {
75
+ const feature = Number(value[i * 8 + j] ?? 0);
76
+ byte |= feature << (backward ? j : 7 - j);
77
+ }
78
+ if (backward) {
79
+ bytesToAdd.unshift(byte);
80
+ } else {
81
+ bytesToAdd.push(byte);
82
+ }
83
+ }
84
+
85
+ bytes.set(bytesToAdd, offset);
86
+ return size;
87
+ },
88
+ });
89
+ }
90
+
91
+ /**
92
+ * Returns a decoder that unpacks bits into an array of booleans.
93
+ *
94
+ * This decoder converts a compact bit representation back into a list of `boolean` values.
95
+ * Each byte is expanded into 8 booleans.
96
+ *
97
+ * The `backward` config option determines whether the bits are read in MSB-first (`false`)
98
+ * or LSB-first (`true`).
99
+ *
100
+ * For more details, see {@link getBitArrayCodec}.
101
+ *
102
+ * @typeParam TSize - The number of bytes used to store the bit array.
103
+ *
104
+ * @param size - The number of bytes allocated for the bit array (must be sufficient for the expected boolean count).
105
+ * @param config - Configuration options for decoding the bit array.
106
+ * @returns A `FixedSizeDecoder<boolean[], TSize>` for decoding bit arrays.
107
+ *
108
+ * @example
109
+ * Decoding a bit array.
110
+ * ```ts
111
+ * const decoder = getBitArrayDecoder(1);
112
+ *
113
+ * decoder.decode(new Uint8Array([0xa0]));
114
+ * // [true, false, true, false, false, false, false, false]
115
+ * ```
116
+ *
117
+ * @see {@link getBitArrayCodec}
118
+ */
119
+ export function getBitArrayDecoder<TSize extends number>(
120
+ size: TSize,
121
+ config: BitArrayCodecConfig | boolean = {},
122
+ ): FixedSizeDecoder<boolean[], TSize> {
123
+ const parsedConfig: BitArrayCodecConfig = typeof config === 'boolean' ? { backward: config } : config;
124
+ const backward = parsedConfig.backward ?? false;
125
+ return createDecoder({
126
+ fixedSize: size,
127
+ read(bytes, offset) {
128
+ assertByteArrayHasEnoughBytesForCodec('bitArray', size, bytes, offset);
129
+ const booleans: boolean[] = [];
130
+ let slice = bytes.slice(offset, offset + size);
131
+ slice = backward ? slice.reverse() : slice;
132
+
133
+ slice.forEach(byte => {
134
+ for (let i = 0; i < 8; i += 1) {
135
+ if (backward) {
136
+ booleans.push(Boolean(byte & 1));
137
+ byte >>= 1;
138
+ } else {
139
+ booleans.push(Boolean(byte & 0b1000_0000));
140
+ byte <<= 1;
141
+ }
142
+ }
143
+ });
144
+
145
+ return [booleans, offset + size];
146
+ },
147
+ });
148
+ }
149
+
150
+ /**
151
+ * Returns a codec that encodes and decodes boolean arrays as compact bit representations.
152
+ *
153
+ * This codec efficiently stores boolean arrays as bits, packing 8 values per byte.
154
+ * The `backward` config option determines whether bits are stored in MSB-first (`false`)
155
+ * or LSB-first (`true`).
156
+ *
157
+ * @typeParam TSize - The number of bytes used to store the bit array.
158
+ *
159
+ * @param size - The number of bytes allocated for the bit array (must be sufficient for the expected boolean count).
160
+ * @param config - Configuration options for encoding and decoding the bit array.
161
+ * @returns A `FixedSizeCodec<boolean[], boolean[], TSize>` for encoding and decoding bit arrays.
162
+ *
163
+ * @example
164
+ * Encoding and decoding a bit array.
165
+ * ```ts
166
+ * const codec = getBitArrayCodec(1);
167
+ *
168
+ * codec.encode([true, false, true, false, false, false, false, false]);
169
+ * // 0xa0 (0b10100000)
170
+ *
171
+ * codec.decode(new Uint8Array([0xa0]));
172
+ * // [true, false, true, false, false, false, false, false]
173
+ * ```
174
+ *
175
+ * @example
176
+ * Encoding and decoding a bit array backwards.
177
+ * ```ts
178
+ * const codec = getBitArrayCodec(1, { backward: true });
179
+ *
180
+ * codec.encode([true, false, true, false, false, false, false, false]);
181
+ * // 0x05 (0b00000101)
182
+ *
183
+ * codec.decode(new Uint8Array([0x05]));
184
+ * // [true, false, true, false, false, false, false, false]
185
+ * ```
186
+ *
187
+ * @remarks
188
+ * Separate {@link getBitArrayEncoder} and {@link getBitArrayDecoder} functions are available.
189
+ *
190
+ * ```ts
191
+ * const bytes = getBitArrayEncoder(1).encode([true, false, true, false]);
192
+ * const value = getBitArrayDecoder(1).decode(bytes);
193
+ * ```
194
+ *
195
+ * @see {@link getBitArrayEncoder}
196
+ * @see {@link getBitArrayDecoder}
197
+ */
198
+ export function getBitArrayCodec<TSize extends number>(
199
+ size: TSize,
200
+ config: BitArrayCodecConfig | boolean = {},
201
+ ): FixedSizeCodec<boolean[], boolean[], TSize> {
202
+ return combineCodec(getBitArrayEncoder(size, config), getBitArrayDecoder(size, config));
203
+ }