@solana/codecs-core 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.
@@ -0,0 +1,209 @@
1
+ import { SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, SolanaError } from '@solana/errors';
2
+
3
+ import {
4
+ Codec,
5
+ createDecoder,
6
+ createEncoder,
7
+ Decoder,
8
+ Encoder,
9
+ FixedSizeCodec,
10
+ FixedSizeDecoder,
11
+ FixedSizeEncoder,
12
+ isFixedSize,
13
+ } from './codec';
14
+ import { combineCodec } from './combine-codec';
15
+
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ type AnyEncoder = Encoder<any>;
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ type AnyDecoder = Decoder<any>;
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ type AnyCodec = Codec<any>;
22
+
23
+ /**
24
+ * Updates the size of a given encoder.
25
+ *
26
+ * This function modifies the size of an encoder using a provided transformation function.
27
+ * For fixed-size encoders, it updates the `fixedSize` property, and for variable-size
28
+ * encoders, it adjusts the size calculation based on the encoded value.
29
+ *
30
+ * If the new size is negative, an error will be thrown.
31
+ *
32
+ * For more details, see {@link resizeCodec}.
33
+ *
34
+ * @typeParam TFrom - The type of the value to encode.
35
+ * @typeParam TSize - The original fixed size of the encoded value.
36
+ * @typeParam TNewSize - The new fixed size after resizing.
37
+ *
38
+ * @param encoder - The encoder whose size will be updated.
39
+ * @param resize - A function that takes the current size and returns the new size.
40
+ * @returns A new encoder with the updated size.
41
+ *
42
+ * @example
43
+ * Increasing the size of a `u16` encoder by 2 bytes.
44
+ * ```ts
45
+ * const encoder = resizeEncoder(getU16Encoder(), size => size + 2);
46
+ * encoder.encode(0xffff); // 0xffff0000 (two extra bytes added)
47
+ * ```
48
+ *
49
+ * @example
50
+ * Shrinking a `u32` encoder to only use 2 bytes.
51
+ * ```ts
52
+ * const encoder = resizeEncoder(getU32Encoder(), () => 2);
53
+ * encoder.fixedSize; // 2
54
+ * ```
55
+ *
56
+ * @see {@link resizeCodec}
57
+ * @see {@link resizeDecoder}
58
+ */
59
+ export function resizeEncoder<TFrom, TSize extends number, TNewSize extends number>(
60
+ encoder: FixedSizeEncoder<TFrom, TSize>,
61
+ resize: (size: TSize) => TNewSize,
62
+ ): FixedSizeEncoder<TFrom, TNewSize>;
63
+ export function resizeEncoder<TEncoder extends AnyEncoder>(
64
+ encoder: TEncoder,
65
+ resize: (size: number) => number,
66
+ ): TEncoder;
67
+ export function resizeEncoder<TEncoder extends AnyEncoder>(
68
+ encoder: TEncoder,
69
+ resize: (size: number) => number,
70
+ ): TEncoder {
71
+ if (isFixedSize(encoder)) {
72
+ const fixedSize = resize(encoder.fixedSize);
73
+ if (fixedSize < 0) {
74
+ throw new SolanaError(SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
75
+ bytesLength: fixedSize,
76
+ codecDescription: 'resizeEncoder',
77
+ });
78
+ }
79
+ return createEncoder({ ...encoder, fixedSize }) as TEncoder;
80
+ }
81
+ return createEncoder({
82
+ ...encoder,
83
+ getSizeFromValue: value => {
84
+ const newSize = resize(encoder.getSizeFromValue(value));
85
+ if (newSize < 0) {
86
+ throw new SolanaError(SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
87
+ bytesLength: newSize,
88
+ codecDescription: 'resizeEncoder',
89
+ });
90
+ }
91
+ return newSize;
92
+ },
93
+ }) as TEncoder;
94
+ }
95
+
96
+ /**
97
+ * Updates the size of a given decoder.
98
+ *
99
+ * This function modifies the size of a decoder using a provided transformation function.
100
+ * For fixed-size decoders, it updates the `fixedSize` property to reflect the new size.
101
+ * Variable-size decoders remain unchanged, as their size is determined dynamically.
102
+ *
103
+ * If the new size is negative, an error will be thrown.
104
+ *
105
+ * For more details, see {@link resizeCodec}.
106
+ *
107
+ * @typeParam TTo - The type of the decoded value.
108
+ * @typeParam TSize - The original fixed size of the decoded value.
109
+ * @typeParam TNewSize - The new fixed size after resizing.
110
+ *
111
+ * @param decoder - The decoder whose size will be updated.
112
+ * @param resize - A function that takes the current size and returns the new size.
113
+ * @returns A new decoder with the updated size.
114
+ *
115
+ * @example
116
+ * Expanding a `u16` decoder to read 4 bytes instead of 2.
117
+ * ```ts
118
+ * const decoder = resizeDecoder(getU16Decoder(), size => size + 2);
119
+ * decoder.fixedSize; // 4
120
+ * ```
121
+ *
122
+ * @example
123
+ * Shrinking a `u32` decoder to only read 2 bytes.
124
+ * ```ts
125
+ * const decoder = resizeDecoder(getU32Decoder(), () => 2);
126
+ * decoder.fixedSize; // 2
127
+ * ```
128
+ *
129
+ * @see {@link resizeCodec}
130
+ * @see {@link resizeEncoder}
131
+ */
132
+ export function resizeDecoder<TFrom, TSize extends number, TNewSize extends number>(
133
+ decoder: FixedSizeDecoder<TFrom, TSize>,
134
+ resize: (size: TSize) => TNewSize,
135
+ ): FixedSizeDecoder<TFrom, TNewSize>;
136
+ export function resizeDecoder<TDecoder extends AnyDecoder>(
137
+ decoder: TDecoder,
138
+ resize: (size: number) => number,
139
+ ): TDecoder;
140
+ export function resizeDecoder<TDecoder extends AnyDecoder>(
141
+ decoder: TDecoder,
142
+ resize: (size: number) => number,
143
+ ): TDecoder {
144
+ if (isFixedSize(decoder)) {
145
+ const fixedSize = resize(decoder.fixedSize);
146
+ if (fixedSize < 0) {
147
+ throw new SolanaError(SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
148
+ bytesLength: fixedSize,
149
+ codecDescription: 'resizeDecoder',
150
+ });
151
+ }
152
+ return createDecoder({ ...decoder, fixedSize }) as TDecoder;
153
+ }
154
+ return decoder;
155
+ }
156
+
157
+ /**
158
+ * Updates the size of a given codec.
159
+ *
160
+ * This function modifies the size of both the codec using a provided
161
+ * transformation function. It is useful for adjusting the allocated byte size for
162
+ * encoding and decoding without altering the underlying data structure.
163
+ *
164
+ * If the new size is negative, an error will be thrown.
165
+ *
166
+ * @typeParam TFrom - The type of the value to encode.
167
+ * @typeParam TTo - The type of the decoded value.
168
+ * @typeParam TSize - The original fixed size of the encoded/decoded value (for fixed-size codecs).
169
+ * @typeParam TNewSize - The new fixed size after resizing (for fixed-size codecs).
170
+ *
171
+ * @param codec - The codec whose size will be updated.
172
+ * @param resize - A function that takes the current size and returns the new size.
173
+ * @returns A new codec with the updated size.
174
+ *
175
+ * @example
176
+ * Expanding a `u16` codec from 2 to 4 bytes.
177
+ * ```ts
178
+ * const codec = resizeCodec(getU16Codec(), size => size + 2);
179
+ * const bytes = codec.encode(0xffff); // 0xffff0000 (two extra bytes added)
180
+ * const value = codec.decode(bytes); // 0xffff (reads original two bytes)
181
+ * ```
182
+ *
183
+ * @example
184
+ * Shrinking a `u32` codec to only use 2 bytes.
185
+ * ```ts
186
+ * const codec = resizeCodec(getU32Codec(), () => 2);
187
+ * codec.fixedSize; // 2
188
+ * ```
189
+ *
190
+ * @remarks
191
+ * If you only need to resize an encoder, use {@link resizeEncoder}.
192
+ * If you only need to resize a decoder, use {@link resizeDecoder}.
193
+ *
194
+ * ```ts
195
+ * const bytes = resizeEncoder(getU32Encoder(), (size) => size + 2).encode(0xffff);
196
+ * const value = resizeDecoder(getU32Decoder(), (size) => size + 2).decode(bytes);
197
+ * ```
198
+ *
199
+ * @see {@link resizeEncoder}
200
+ * @see {@link resizeDecoder}
201
+ */
202
+ export function resizeCodec<TFrom, TTo extends TFrom, TSize extends number, TNewSize extends number>(
203
+ codec: FixedSizeCodec<TFrom, TTo, TSize>,
204
+ resize: (size: TSize) => TNewSize,
205
+ ): FixedSizeCodec<TFrom, TTo, TNewSize>;
206
+ export function resizeCodec<TCodec extends AnyCodec>(codec: TCodec, resize: (size: number) => number): TCodec;
207
+ export function resizeCodec<TCodec extends AnyCodec>(codec: TCodec, resize: (size: number) => number): TCodec {
208
+ return combineCodec(resizeEncoder(codec, resize), resizeDecoder(codec, resize)) as TCodec;
209
+ }
@@ -0,0 +1,159 @@
1
+ import {
2
+ assertIsFixedSize,
3
+ createDecoder,
4
+ createEncoder,
5
+ FixedSizeCodec,
6
+ FixedSizeDecoder,
7
+ FixedSizeEncoder,
8
+ } from './codec';
9
+ import { combineCodec } from './combine-codec';
10
+ import { ReadonlyUint8Array } from './readonly-uint8array';
11
+
12
+ function copySourceToTargetInReverse(
13
+ source: ReadonlyUint8Array,
14
+ target_WILL_MUTATE: Uint8Array,
15
+ sourceOffset: number,
16
+ sourceLength: number,
17
+ targetOffset: number = 0,
18
+ ) {
19
+ while (sourceOffset < --sourceLength) {
20
+ const leftValue = source[sourceOffset];
21
+ target_WILL_MUTATE[sourceOffset + targetOffset] = source[sourceLength];
22
+ target_WILL_MUTATE[sourceLength + targetOffset] = leftValue;
23
+ sourceOffset++;
24
+ }
25
+ if (sourceOffset === sourceLength) {
26
+ target_WILL_MUTATE[sourceOffset + targetOffset] = source[sourceOffset];
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Reverses the bytes of a fixed-size encoder.
32
+ *
33
+ * Given a `FixedSizeEncoder`, this function returns a new `FixedSizeEncoder` that
34
+ * reverses the bytes within the fixed-size byte array when encoding.
35
+ *
36
+ * This can be useful to modify endianness or for other byte-order transformations.
37
+ *
38
+ * For more details, see {@link reverseCodec}.
39
+ *
40
+ * @typeParam TFrom - The type of the value to encode.
41
+ * @typeParam TSize - The fixed size of the encoded value in bytes.
42
+ *
43
+ * @param encoder - The fixed-size encoder to reverse.
44
+ * @returns A new encoder that writes bytes in reverse order.
45
+ *
46
+ * @example
47
+ * Encoding a `u16` value in reverse order.
48
+ * ```ts
49
+ * const encoder = reverseEncoder(getU16Encoder({ endian: Endian.Big }));
50
+ * const bytes = encoder.encode(0x1234); // 0x3412 (bytes are flipped)
51
+ * ```
52
+ *
53
+ * @see {@link reverseCodec}
54
+ * @see {@link reverseDecoder}
55
+ */
56
+ export function reverseEncoder<TFrom, TSize extends number>(
57
+ encoder: FixedSizeEncoder<TFrom, TSize>,
58
+ ): FixedSizeEncoder<TFrom, TSize> {
59
+ assertIsFixedSize(encoder);
60
+ return createEncoder({
61
+ ...encoder,
62
+ write: (value: TFrom, bytes, offset) => {
63
+ const newOffset = encoder.write(value, bytes, offset);
64
+ copySourceToTargetInReverse(
65
+ bytes /* source */,
66
+ bytes /* target_WILL_MUTATE */,
67
+ offset /* sourceOffset */,
68
+ offset + encoder.fixedSize /* sourceLength */,
69
+ );
70
+ return newOffset;
71
+ },
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Reverses the bytes of a fixed-size decoder.
77
+ *
78
+ * Given a `FixedSizeDecoder`, this function returns a new `FixedSizeDecoder` that
79
+ * reverses the bytes within the fixed-size byte array before decoding.
80
+ *
81
+ * This can be useful to modify endianness or for other byte-order transformations.
82
+ *
83
+ * For more details, see {@link reverseCodec}.
84
+ *
85
+ * @typeParam TTo - The type of the decoded value.
86
+ * @typeParam TSize - The fixed size of the decoded value in bytes.
87
+ *
88
+ * @param decoder - The fixed-size decoder to reverse.
89
+ * @returns A new decoder that reads bytes in reverse order.
90
+ *
91
+ * @example
92
+ * Decoding a reversed `u16` value.
93
+ * ```ts
94
+ * const decoder = reverseDecoder(getU16Decoder({ endian: Endian.Big }));
95
+ * const value = decoder.decode(new Uint8Array([0x34, 0x12])); // 0x1234 (bytes are flipped back)
96
+ * ```
97
+ *
98
+ * @see {@link reverseCodec}
99
+ * @see {@link reverseEncoder}
100
+ */
101
+ export function reverseDecoder<TTo, TSize extends number>(
102
+ decoder: FixedSizeDecoder<TTo, TSize>,
103
+ ): FixedSizeDecoder<TTo, TSize> {
104
+ assertIsFixedSize(decoder);
105
+ return createDecoder({
106
+ ...decoder,
107
+ read: (bytes, offset) => {
108
+ const reversedBytes = bytes.slice();
109
+ copySourceToTargetInReverse(
110
+ bytes /* source */,
111
+ reversedBytes /* target_WILL_MUTATE */,
112
+ offset /* sourceOffset */,
113
+ offset + decoder.fixedSize /* sourceLength */,
114
+ );
115
+ return decoder.read(reversedBytes, offset);
116
+ },
117
+ });
118
+ }
119
+
120
+ /**
121
+ * Reverses the bytes of a fixed-size codec.
122
+ *
123
+ * Given a `FixedSizeCodec`, this function returns a new `FixedSizeCodec` that
124
+ * reverses the bytes within the fixed-size byte array during encoding and decoding.
125
+ *
126
+ * This can be useful to modify endianness or for other byte-order transformations.
127
+ *
128
+ * @typeParam TFrom - The type of the value to encode.
129
+ * @typeParam TTo - The type of the decoded value.
130
+ * @typeParam TSize - The fixed size of the encoded/decoded value in bytes.
131
+ *
132
+ * @param codec - The fixed-size codec to reverse.
133
+ * @returns A new codec that encodes and decodes bytes in reverse order.
134
+ *
135
+ * @example
136
+ * Reversing a `u16` codec.
137
+ * ```ts
138
+ * const codec = reverseCodec(getU16Codec({ endian: Endian.Big }));
139
+ * const bytes = codec.encode(0x1234); // 0x3412 (bytes are flipped)
140
+ * const value = codec.decode(bytes); // 0x1234 (bytes are flipped back)
141
+ * ```
142
+ *
143
+ * @remarks
144
+ * If you only need to reverse an encoder, use {@link reverseEncoder}.
145
+ * If you only need to reverse a decoder, use {@link reverseDecoder}.
146
+ *
147
+ * ```ts
148
+ * const bytes = reverseEncoder(getU16Encoder()).encode(0x1234);
149
+ * const value = reverseDecoder(getU16Decoder()).decode(bytes);
150
+ * ```
151
+ *
152
+ * @see {@link reverseEncoder}
153
+ * @see {@link reverseDecoder}
154
+ */
155
+ export function reverseCodec<TFrom, TTo extends TFrom, TSize extends number>(
156
+ codec: FixedSizeCodec<TFrom, TTo, TSize>,
157
+ ): FixedSizeCodec<TFrom, TTo, TSize> {
158
+ return combineCodec(reverseEncoder(codec), reverseDecoder(codec));
159
+ }
@@ -0,0 +1,208 @@
1
+ import {
2
+ Codec,
3
+ createCodec,
4
+ createDecoder,
5
+ createEncoder,
6
+ Decoder,
7
+ Encoder,
8
+ FixedSizeCodec,
9
+ FixedSizeDecoder,
10
+ FixedSizeEncoder,
11
+ isVariableSize,
12
+ VariableSizeCodec,
13
+ VariableSizeDecoder,
14
+ VariableSizeEncoder,
15
+ } from './codec';
16
+ import { ReadonlyUint8Array } from './readonly-uint8array';
17
+
18
+ /**
19
+ * Transforms an encoder by mapping its input values.
20
+ *
21
+ * This function takes an existing `Encoder<A>` and returns an `Encoder<B>`, allowing values of type `B`
22
+ * to be converted into values of type `A` before encoding. The transformation is applied via the `unmap` function.
23
+ *
24
+ * This is useful for handling type conversions, applying default values, or structuring data before encoding.
25
+ *
26
+ * For more details, see {@link transformCodec}.
27
+ *
28
+ * @typeParam TOldFrom - The original type expected by the encoder.
29
+ * @typeParam TNewFrom - The new type that will be transformed before encoding.
30
+ *
31
+ * @param encoder - The encoder to transform.
32
+ * @param unmap - A function that converts values of `TNewFrom` into `TOldFrom` before encoding.
33
+ * @returns A new encoder that accepts `TNewFrom` values and transforms them before encoding.
34
+ *
35
+ * @example
36
+ * Encoding a string by counting its characters and storing the length as a `u32`.
37
+ * ```ts
38
+ * const encoder = transformEncoder(getU32Encoder(), (value: string) => value.length);
39
+ * encoder.encode("hello"); // 0x05000000 (stores length 5)
40
+ * ```
41
+ *
42
+ * @see {@link transformCodec}
43
+ * @see {@link transformDecoder}
44
+ */
45
+ export function transformEncoder<TOldFrom, TNewFrom, TSize extends number>(
46
+ encoder: FixedSizeEncoder<TOldFrom, TSize>,
47
+ unmap: (value: TNewFrom) => TOldFrom,
48
+ ): FixedSizeEncoder<TNewFrom, TSize>;
49
+ export function transformEncoder<TOldFrom, TNewFrom>(
50
+ encoder: VariableSizeEncoder<TOldFrom>,
51
+ unmap: (value: TNewFrom) => TOldFrom,
52
+ ): VariableSizeEncoder<TNewFrom>;
53
+ export function transformEncoder<TOldFrom, TNewFrom>(
54
+ encoder: Encoder<TOldFrom>,
55
+ unmap: (value: TNewFrom) => TOldFrom,
56
+ ): Encoder<TNewFrom>;
57
+ export function transformEncoder<TOldFrom, TNewFrom>(
58
+ encoder: Encoder<TOldFrom>,
59
+ unmap: (value: TNewFrom) => TOldFrom,
60
+ ): Encoder<TNewFrom> {
61
+ return createEncoder({
62
+ ...(isVariableSize(encoder)
63
+ ? { ...encoder, getSizeFromValue: (value: TNewFrom) => encoder.getSizeFromValue(unmap(value)) }
64
+ : encoder),
65
+ write: (value: TNewFrom, bytes, offset) => encoder.write(unmap(value), bytes, offset),
66
+ });
67
+ }
68
+
69
+ /**
70
+ * Transforms a decoder by mapping its output values.
71
+ *
72
+ * This function takes an existing `Decoder<A>` and returns a `Decoder<B>`, allowing values of type `A`
73
+ * to be converted into values of type `B` after decoding. The transformation is applied via the `map` function.
74
+ *
75
+ * This is useful for post-processing, type conversions, or enriching decoded data.
76
+ *
77
+ * For more details, see {@link transformCodec}.
78
+ *
79
+ * @typeParam TOldTo - The original type returned by the decoder.
80
+ * @typeParam TNewTo - The new type that will be transformed after decoding.
81
+ *
82
+ * @param decoder - The decoder to transform.
83
+ * @param map - A function that converts values of `TOldTo` into `TNewTo` after decoding.
84
+ * @returns A new decoder that decodes into `TNewTo`.
85
+ *
86
+ * @example
87
+ * Decoding a stored `u32` length into a string of `'x'` characters.
88
+ * ```ts
89
+ * const decoder = transformDecoder(getU32Decoder(), (length) => 'x'.repeat(length));
90
+ * decoder.decode(new Uint8Array([0x05, 0x00, 0x00, 0x00])); // "xxxxx"
91
+ * ```
92
+ *
93
+ * @see {@link transformCodec}
94
+ * @see {@link transformEncoder}
95
+ */
96
+ export function transformDecoder<TOldTo, TNewTo, TSize extends number>(
97
+ decoder: FixedSizeDecoder<TOldTo, TSize>,
98
+ map: (value: TOldTo, bytes: ReadonlyUint8Array | Uint8Array, offset: number) => TNewTo,
99
+ ): FixedSizeDecoder<TNewTo, TSize>;
100
+ export function transformDecoder<TOldTo, TNewTo>(
101
+ decoder: VariableSizeDecoder<TOldTo>,
102
+ map: (value: TOldTo, bytes: ReadonlyUint8Array | Uint8Array, offset: number) => TNewTo,
103
+ ): VariableSizeDecoder<TNewTo>;
104
+ export function transformDecoder<TOldTo, TNewTo>(
105
+ decoder: Decoder<TOldTo>,
106
+ map: (value: TOldTo, bytes: ReadonlyUint8Array | Uint8Array, offset: number) => TNewTo,
107
+ ): Decoder<TNewTo>;
108
+ export function transformDecoder<TOldTo, TNewTo>(
109
+ decoder: Decoder<TOldTo>,
110
+ map: (value: TOldTo, bytes: ReadonlyUint8Array | Uint8Array, offset: number) => TNewTo,
111
+ ): Decoder<TNewTo> {
112
+ return createDecoder({
113
+ ...decoder,
114
+ read: (bytes: ReadonlyUint8Array | Uint8Array, offset) => {
115
+ const [value, newOffset] = decoder.read(bytes, offset);
116
+ return [map(value, bytes, offset), newOffset];
117
+ },
118
+ });
119
+ }
120
+
121
+ /**
122
+ * Transforms a codec by mapping its input and output values.
123
+ *
124
+ * This function takes an existing `Codec<A, B>` and returns a `Codec<C, D>`, allowing:
125
+ * - Values of type `C` to be transformed into `A` before encoding.
126
+ * - Values of type `B` to be transformed into `D` after decoding.
127
+ *
128
+ * This is useful for adapting codecs to work with different representations, handling default values, or
129
+ * converting between primitive and structured types.
130
+ *
131
+ * @typeParam TOldFrom - The original type expected by the codec.
132
+ * @typeParam TNewFrom - The new type that will be transformed before encoding.
133
+ * @typeParam TOldTo - The original type returned by the codec.
134
+ * @typeParam TNewTo - The new type that will be transformed after decoding.
135
+ *
136
+ * @param codec - The codec to transform.
137
+ * @param unmap - A function that converts values of `TNewFrom` into `TOldFrom` before encoding.
138
+ * @param map - A function that converts values of `TOldTo` into `TNewTo` after decoding (optional).
139
+ * @returns A new codec that encodes `TNewFrom` and decodes into `TNewTo`.
140
+ *
141
+ * @example
142
+ * Mapping a `u32` codec to encode string lengths and decode them into `'x'` characters.
143
+ * ```ts
144
+ * const codec = transformCodec(
145
+ * getU32Codec(),
146
+ * (value: string) => value.length, // Encode string length
147
+ * (length) => 'x'.repeat(length) // Decode length into a string of 'x's
148
+ * );
149
+ *
150
+ * const bytes = codec.encode("hello"); // 0x05000000 (stores length 5)
151
+ * const value = codec.decode(bytes); // "xxxxx"
152
+ * ```
153
+ *
154
+ * @remarks
155
+ * If only input transformation is needed, use {@link transformEncoder}.
156
+ * If only output transformation is needed, use {@link transformDecoder}.
157
+ *
158
+ * ```ts
159
+ * const bytes = transformEncoder(getU32Encoder(), (value: string) => value.length).encode("hello");
160
+ * const value = transformDecoder(getU32Decoder(), (length) => 'x'.repeat(length)).decode(bytes);
161
+ * ```
162
+ *
163
+ * @see {@link transformEncoder}
164
+ * @see {@link transformDecoder}
165
+ */
166
+ export function transformCodec<TOldFrom, TNewFrom, TTo extends TNewFrom & TOldFrom, TSize extends number>(
167
+ codec: FixedSizeCodec<TOldFrom, TTo, TSize>,
168
+ unmap: (value: TNewFrom) => TOldFrom,
169
+ ): FixedSizeCodec<TNewFrom, TTo, TSize>;
170
+ export function transformCodec<TOldFrom, TNewFrom, TTo extends TNewFrom & TOldFrom>(
171
+ codec: VariableSizeCodec<TOldFrom, TTo>,
172
+ unmap: (value: TNewFrom) => TOldFrom,
173
+ ): VariableSizeCodec<TNewFrom, TTo>;
174
+ export function transformCodec<TOldFrom, TNewFrom, TTo extends TNewFrom & TOldFrom>(
175
+ codec: Codec<TOldFrom, TTo>,
176
+ unmap: (value: TNewFrom) => TOldFrom,
177
+ ): Codec<TNewFrom, TTo>;
178
+ export function transformCodec<
179
+ TOldFrom,
180
+ TNewFrom,
181
+ TOldTo extends TOldFrom,
182
+ TNewTo extends TNewFrom,
183
+ TSize extends number,
184
+ >(
185
+ codec: FixedSizeCodec<TOldFrom, TOldTo, TSize>,
186
+ unmap: (value: TNewFrom) => TOldFrom,
187
+ map: (value: TOldTo, bytes: ReadonlyUint8Array | Uint8Array, offset: number) => TNewTo,
188
+ ): FixedSizeCodec<TNewFrom, TNewTo, TSize>;
189
+ export function transformCodec<TOldFrom, TNewFrom, TOldTo extends TOldFrom, TNewTo extends TNewFrom>(
190
+ codec: VariableSizeCodec<TOldFrom, TOldTo>,
191
+ unmap: (value: TNewFrom) => TOldFrom,
192
+ map: (value: TOldTo, bytes: ReadonlyUint8Array | Uint8Array, offset: number) => TNewTo,
193
+ ): VariableSizeCodec<TNewFrom, TNewTo>;
194
+ export function transformCodec<TOldFrom, TNewFrom, TOldTo extends TOldFrom, TNewTo extends TNewFrom>(
195
+ codec: Codec<TOldFrom, TOldTo>,
196
+ unmap: (value: TNewFrom) => TOldFrom,
197
+ map: (value: TOldTo, bytes: ReadonlyUint8Array | Uint8Array, offset: number) => TNewTo,
198
+ ): Codec<TNewFrom, TNewTo>;
199
+ export function transformCodec<TOldFrom, TNewFrom, TOldTo extends TOldFrom, TNewTo extends TNewFrom>(
200
+ codec: Codec<TOldFrom, TOldTo>,
201
+ unmap: (value: TNewFrom) => TOldFrom,
202
+ map?: (value: TOldTo, bytes: ReadonlyUint8Array | Uint8Array, offset: number) => TNewTo,
203
+ ): Codec<TNewFrom, TNewTo> {
204
+ return createCodec({
205
+ ...transformEncoder(codec, unmap),
206
+ read: map ? transformDecoder(codec, map).read : (codec.read as unknown as Decoder<TNewTo>['read']),
207
+ });
208
+ }