@solana/codecs-strings 2.0.0-experimental.ffeddf6 → 2.0.0-preview.1
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/README.md +194 -4
- package/dist/index.browser.cjs +148 -132
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +149 -133
- package/dist/index.browser.js.map +1 -1
- package/dist/index.native.js +120 -117
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +130 -130
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +131 -131
- package/dist/index.node.js.map +1 -1
- package/dist/types/assertions.d.ts.map +1 -0
- package/dist/types/base10.d.ts +3 -3
- package/dist/types/base10.d.ts.map +1 -0
- package/dist/types/base16.d.ts +4 -4
- package/dist/types/base16.d.ts.map +1 -0
- package/dist/types/base58.d.ts +3 -3
- package/dist/types/base58.d.ts.map +1 -0
- package/dist/types/base64.d.ts +4 -4
- package/dist/types/base64.d.ts.map +1 -0
- package/dist/types/baseX-reslice.d.ts +4 -4
- package/dist/types/baseX-reslice.d.ts.map +1 -0
- package/dist/types/baseX.d.ts +4 -4
- package/dist/types/baseX.d.ts.map +1 -0
- package/dist/types/index.d.ts +10 -10
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/null-characters.d.ts.map +1 -0
- package/dist/types/string.d.ts +32 -11
- package/dist/types/string.d.ts.map +1 -0
- package/dist/types/utf8.d.ts +3 -3
- package/dist/types/utf8.d.ts.map +1 -0
- package/package.json +14 -34
- package/dist/index.development.js +0 -469
- package/dist/index.development.js.map +0 -1
- package/dist/index.production.min.js +0 -37
package/README.md
CHANGED
|
@@ -16,10 +16,200 @@
|
|
|
16
16
|
|
|
17
17
|
This package contains codecs for strings of different sizes and encodings. It can be used standalone, but it is also exported as part of the Solana JavaScript SDK [`@solana/web3.js@experimental`](https://github.com/solana-labs/solana-web3.js/tree/master/packages/library).
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
This package is also part of the [`@solana/codecs` package](https://github.com/solana-labs/solana-web3.js/tree/master/packages/codecs) which acts as an entry point for all codec packages as well as for their documentation.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
## String helper codec
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
The `getStringCodec` function returns a `Codec<string>` that can be used to encode strings using various encodings and size strategies. It contains the following options:
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
- `encoding`: A `VariableSizeCodec<string>` responsible for encoding and decoding a string in a specific way without worrying about its size. Examples are UTF-8, base58, base64, etc. You can see all available encodings below in this documentation.
|
|
26
|
+
- `size`: This option tells the codec how long the string goes on for in the byte array. It can be one of the following three strategies:
|
|
27
|
+
- `Codec<number>`: When a number codec is provided, that codec will be used to encode and decode a size prefix for that string. This prefix allows us to know when to stop reading the string when decoding a given byte array.
|
|
28
|
+
- `number`: When a fixed number is provided, a `FixedSizeCodec` of that size will be returned such that exactly that amount of bytes will be used to encode and decode the string.
|
|
29
|
+
- `"variable"`: When the string `"variable"` is passed as a size, a `VariableSizeCodec` will be returned without any size boundary. That is, when providing a byte array to decode, the entire byte array will be decoded as a string.
|
|
30
|
+
|
|
31
|
+
When using `getStringCodec` without any options, the default encoding used is UTF-8 and the default size strategy used is a `u32` prefix codec.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const bytes = getStringCodec().encode('hello');
|
|
35
|
+
// 0x0500000068656c6c6f
|
|
36
|
+
// | └-- The 5 bytes of content.
|
|
37
|
+
// └-- 4-byte prefix telling us to read 5 bytes.
|
|
38
|
+
|
|
39
|
+
const value = getStringCodec().decode(bytes);
|
|
40
|
+
// "hello"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
We can use the `size` option to provide a different integer codec for the prefix.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
getStringCodec({ size: getU8Codec() }).encode('hello');
|
|
47
|
+
// 0x0568656c6c6f
|
|
48
|
+
// | └-- The 5 bytes of content.
|
|
49
|
+
// └-- 1-byte prefix telling us to read 5 bytes.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or to provide a fixed size such that any string longer or smaller than that size will be truncated or padded respectively.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
getStringCodec({ size: 5 }).encode('hello');
|
|
56
|
+
// 0x68656c6c6f
|
|
57
|
+
// └-- The exact 5 bytes of content.
|
|
58
|
+
|
|
59
|
+
getStringCodec({ size: 5 }).encode('hello world');
|
|
60
|
+
// 0x68656c6c6f
|
|
61
|
+
// └-- The truncated 5 bytes of content.
|
|
62
|
+
|
|
63
|
+
getStringCodec({ size: 5 }).encode('hell');
|
|
64
|
+
// 0x68656c6c00
|
|
65
|
+
// └-- The padded 5 bytes of content.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Or to tell the codec we do not want to create a size boundary for our string.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
getStringCodec({ size: 'variable' }).encode('hello');
|
|
72
|
+
// 0x68656c6c6f
|
|
73
|
+
// └-- Any bytes necessary to encode our content.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
On top of customizing the size, we may provide a custom `encoding` option like so.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
getStringCodec({ encoding: getUtf8Codec() }).encode('hello');
|
|
80
|
+
// 0x0500000068656c6c6f (Default encoding).
|
|
81
|
+
|
|
82
|
+
getStringCodec({ encoding: getBase64Codec() }).encode('hello');
|
|
83
|
+
// 0x0300000085e965
|
|
84
|
+
|
|
85
|
+
getStringCodec({ encoding: getBase58Codec() }).encode('heLLo');
|
|
86
|
+
// 0x040000001b6a3070
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Finally, separate `getStringEncoder` and `getStringDecoder` functions are also available.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
const bytes = getStringEncoder().encode('hello');
|
|
93
|
+
const value = getStringDecoder().decode(bytes);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Utf8 codec
|
|
97
|
+
|
|
98
|
+
The `getUtf8Codec` function encodes and decodes a UTF-8 string to and from a byte array.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const bytes = getUtf8Codec().encode('hello'); // 0x68656c6c6f
|
|
102
|
+
const value = getUtf8Codec().decode(bytes); // "hello"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
As usual, separate `getUtf8Encoder` and `getUtf8Decoder` functions are also available.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
const bytes = getUtf8Encoder().encode('hello'); // 0x68656c6c6f
|
|
109
|
+
const value = getUtf8Decoder().decode(bytes); // "hello"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Base 64 codec
|
|
113
|
+
|
|
114
|
+
The `getBase64Codec` function encodes and decodes a base-64 string to and from a byte array.
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
const bytes = getBase64Codec().encode('hello+world'); // 0x85e965a3ec28ae57
|
|
118
|
+
const value = getBase64Codec().decode(bytes); // "hello+world"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
As usual, separate `getBase64Encoder` and `getBase64Decoder` functions are also available.
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
const bytes = getBase64Encoder().encode('hello+world'); // 0x85e965a3ec28ae57
|
|
125
|
+
const value = getBase64Decoder().decode(bytes); // "hello+world"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Base 58 codec
|
|
129
|
+
|
|
130
|
+
The `getBase58Codec` function encodes and decodes a base-58 string to and from a byte array.
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const bytes = getBase58Codec().encode('heLLo'); // 0x1b6a3070
|
|
134
|
+
const value = getBase58Codec().decode(bytes); // "heLLo"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
As usual, separate `getBase58Encoder` and `getBase58Decoder` functions are also available.
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
const bytes = getBase58Encoder().encode('heLLo'); // 0x1b6a3070
|
|
141
|
+
const value = getBase58Decoder().decode(bytes); // "heLLo"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Base 16 codec
|
|
145
|
+
|
|
146
|
+
The `getBase16Codec` function encodes and decodes a base-16 string to and from a byte array.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
const bytes = getBase16Codec().encode('deadface'); // 0xdeadface
|
|
150
|
+
const value = getBase16Codec().decode(bytes); // "deadface"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
As usual, separate `getBase16Encoder` and `getBase16Decoder` functions are also available.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
const bytes = getBase16Encoder().encode('deadface'); // 0xdeadface
|
|
157
|
+
const value = getBase16Decoder().decode(bytes); // "deadface"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Base 10 codec
|
|
161
|
+
|
|
162
|
+
The `getBase10Codec` function encodes and decodes a base-10 string to and from a byte array.
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const bytes = getBase10Codec().encode('1024'); // 0x0400
|
|
166
|
+
const value = getBase10Codec().decode(bytes); // "1024"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
As usual, separate `getBase10Encoder` and `getBase10Decoder` functions are also available.
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
const bytes = getBase10Encoder().encode('1024'); // 0x0400
|
|
173
|
+
const value = getBase10Decoder().decode(bytes); // "1024"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Base X codec
|
|
177
|
+
|
|
178
|
+
The `getBaseXCodec` accepts a custom `alphabet` of `X` characters and creates a base-X codec using that alphabet. It does so by iteratively dividing by `X` and handling leading zeros.
|
|
179
|
+
|
|
180
|
+
The base-10 and base-58 codecs use this base-x codec under the hood.
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
const alphabet = '0ehlo';
|
|
184
|
+
const bytes = getBaseXCodec(alphabet).encode('hello'); // 0x05bd
|
|
185
|
+
const value = getBaseXCodec(alphabet).decode(bytes); // "hello"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
As usual, separate `getBaseXEncoder` and `getBaseXDecoder` functions are also available.
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
const bytes = getBaseXEncoder(alphabet).encode('hello'); // 0x05bd
|
|
192
|
+
const value = getBaseXDecoder(alphabet).decode(bytes); // "hello"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Re-slicing base X codec
|
|
196
|
+
|
|
197
|
+
The `getBaseXResliceCodec` also creates a base-x codec but uses a different strategy. It re-slices bytes into custom chunks of bits that are then mapped to a provided `alphabet`. The number of bits per chunk is also provided and should typically be set to `log2(alphabet.length)`.
|
|
198
|
+
|
|
199
|
+
This is typically used to create codecs whose alphabet’s length is a power of 2 such as base-16 or base-64.
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
const bytes = getBaseXResliceCodec('elho', 2).encode('hellolol'); // 0x4aee
|
|
203
|
+
const value = getBaseXResliceCodec('elho', 2).decode(bytes); // "hellolol"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
As usual, separate `getBaseXResliceEncoder` and `getBaseXResliceDecoder` functions are also available.
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
const bytes = getBaseXResliceEncoder('elho', 2).encode('hellolol'); // 0x4aee
|
|
210
|
+
const value = getBaseXResliceDecoder('elho', 2).decode(bytes); // "hellolol"
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
To read more about the available codecs and how to use them, check out the documentation of the main [`@solana/codecs` package](https://github.com/solana-labs/solana-web3.js/tree/master/packages/codecs).
|
package/dist/index.browser.cjs
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var errors = require('@solana/errors');
|
|
3
4
|
var codecsCore = require('@solana/codecs-core');
|
|
4
5
|
var codecsNumbers = require('@solana/codecs-numbers');
|
|
5
6
|
|
|
6
7
|
// src/assertions.ts
|
|
7
8
|
function assertValidBaseString(alphabet4, testValue, givenValue = testValue) {
|
|
8
9
|
if (!testValue.match(new RegExp(`^[${alphabet4}]*$`))) {
|
|
9
|
-
throw new
|
|
10
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__INVALID_STRING_FOR_BASE, {
|
|
11
|
+
alphabet: alphabet4,
|
|
12
|
+
base: alphabet4.length,
|
|
13
|
+
value: givenValue
|
|
14
|
+
});
|
|
10
15
|
}
|
|
11
16
|
}
|
|
12
17
|
var getBaseXEncoder = (alphabet4) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
return codecsCore.createEncoder({
|
|
19
|
+
getSizeFromValue: (value) => {
|
|
20
|
+
const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);
|
|
21
|
+
if (!tailChars)
|
|
22
|
+
return value.length;
|
|
23
|
+
const base10Number = getBigIntFromBaseX(tailChars, alphabet4);
|
|
24
|
+
return leadingZeroes.length + Math.ceil(base10Number.toString(16).length / 2);
|
|
25
|
+
},
|
|
26
|
+
write(value, bytes, offset) {
|
|
18
27
|
assertValidBaseString(alphabet4, value);
|
|
19
28
|
if (value === "")
|
|
20
|
-
return
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (trailIndex === chars.length)
|
|
26
|
-
return Uint8Array.from(leadingZeroes);
|
|
27
|
-
const tailChars = chars.slice(trailIndex);
|
|
28
|
-
let base10Number = 0n;
|
|
29
|
-
let baseXPower = 1n;
|
|
30
|
-
for (let i = tailChars.length - 1; i >= 0; i -= 1) {
|
|
31
|
-
base10Number += baseXPower * BigInt(alphabet4.indexOf(tailChars[i]));
|
|
32
|
-
baseXPower *= baseBigInt;
|
|
29
|
+
return offset;
|
|
30
|
+
const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);
|
|
31
|
+
if (!tailChars) {
|
|
32
|
+
bytes.set(new Uint8Array(leadingZeroes.length).fill(0), offset);
|
|
33
|
+
return offset + leadingZeroes.length;
|
|
33
34
|
}
|
|
35
|
+
let base10Number = getBigIntFromBaseX(tailChars, alphabet4);
|
|
34
36
|
const tailBytes = [];
|
|
35
37
|
while (base10Number > 0n) {
|
|
36
38
|
tailBytes.unshift(Number(base10Number % 256n));
|
|
37
39
|
base10Number /= 256n;
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
};
|
|
41
|
+
const bytesToAdd = [...Array(leadingZeroes.length).fill(0), ...tailBytes];
|
|
42
|
+
bytes.set(bytesToAdd, offset);
|
|
43
|
+
return offset + bytesToAdd.length;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
44
46
|
};
|
|
45
47
|
var getBaseXDecoder = (alphabet4) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
decode(rawBytes, offset = 0) {
|
|
48
|
+
return codecsCore.createDecoder({
|
|
49
|
+
read(rawBytes, offset) {
|
|
50
50
|
const bytes = offset === 0 ? rawBytes : rawBytes.slice(offset);
|
|
51
51
|
if (bytes.length === 0)
|
|
52
52
|
return ["", 0];
|
|
@@ -55,45 +55,57 @@ var getBaseXDecoder = (alphabet4) => {
|
|
|
55
55
|
const leadingZeroes = alphabet4[0].repeat(trailIndex);
|
|
56
56
|
if (trailIndex === bytes.length)
|
|
57
57
|
return [leadingZeroes, rawBytes.length];
|
|
58
|
-
|
|
59
|
-
const tailChars =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
return [leadingZeroes + tailChars.join(""), rawBytes.length];
|
|
65
|
-
},
|
|
66
|
-
description: `base${base}`,
|
|
67
|
-
fixedSize: null,
|
|
68
|
-
maxSize: null
|
|
69
|
-
};
|
|
58
|
+
const base10Number = bytes.slice(trailIndex).reduce((sum, byte) => sum * 256n + BigInt(byte), 0n);
|
|
59
|
+
const tailChars = getBaseXFromBigInt(base10Number, alphabet4);
|
|
60
|
+
return [leadingZeroes + tailChars, rawBytes.length];
|
|
61
|
+
}
|
|
62
|
+
});
|
|
70
63
|
};
|
|
71
64
|
var getBaseXCodec = (alphabet4) => codecsCore.combineCodec(getBaseXEncoder(alphabet4), getBaseXDecoder(alphabet4));
|
|
65
|
+
function partitionLeadingZeroes(value, zeroCharacter) {
|
|
66
|
+
const [leadingZeros, tailChars] = value.split(new RegExp(`((?!${zeroCharacter}).*)`));
|
|
67
|
+
return [leadingZeros, tailChars];
|
|
68
|
+
}
|
|
69
|
+
function getBigIntFromBaseX(value, alphabet4) {
|
|
70
|
+
const base = BigInt(alphabet4.length);
|
|
71
|
+
let sum = 0n;
|
|
72
|
+
for (const char of value) {
|
|
73
|
+
sum *= base;
|
|
74
|
+
sum += BigInt(alphabet4.indexOf(char));
|
|
75
|
+
}
|
|
76
|
+
return sum;
|
|
77
|
+
}
|
|
78
|
+
function getBaseXFromBigInt(value, alphabet4) {
|
|
79
|
+
const base = BigInt(alphabet4.length);
|
|
80
|
+
const tailChars = [];
|
|
81
|
+
while (value > 0n) {
|
|
82
|
+
tailChars.unshift(alphabet4[Number(value % base)]);
|
|
83
|
+
value /= base;
|
|
84
|
+
}
|
|
85
|
+
return tailChars.join("");
|
|
86
|
+
}
|
|
72
87
|
|
|
73
88
|
// src/base10.ts
|
|
74
89
|
var alphabet = "0123456789";
|
|
75
90
|
var getBase10Encoder = () => getBaseXEncoder(alphabet);
|
|
76
91
|
var getBase10Decoder = () => getBaseXDecoder(alphabet);
|
|
77
92
|
var getBase10Codec = () => getBaseXCodec(alphabet);
|
|
78
|
-
var getBase16Encoder = () => ({
|
|
79
|
-
|
|
80
|
-
|
|
93
|
+
var getBase16Encoder = () => codecsCore.createEncoder({
|
|
94
|
+
getSizeFromValue: (value) => Math.ceil(value.length / 2),
|
|
95
|
+
write(value, bytes, offset) {
|
|
81
96
|
const lowercaseValue = value.toLowerCase();
|
|
82
97
|
assertValidBaseString("0123456789abcdef", lowercaseValue, value);
|
|
83
98
|
const matches = lowercaseValue.match(/.{1,2}/g);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
99
|
+
const hexBytes = matches ? matches.map((byte) => parseInt(byte, 16)) : [];
|
|
100
|
+
bytes.set(hexBytes, offset);
|
|
101
|
+
return hexBytes.length + offset;
|
|
102
|
+
}
|
|
88
103
|
});
|
|
89
|
-
var getBase16Decoder = () => ({
|
|
90
|
-
|
|
104
|
+
var getBase16Decoder = () => codecsCore.createDecoder({
|
|
105
|
+
read(bytes, offset) {
|
|
91
106
|
const value = bytes.slice(offset).reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
|
|
92
107
|
return [value, bytes.length];
|
|
93
|
-
}
|
|
94
|
-
description: "base16",
|
|
95
|
-
fixedSize: null,
|
|
96
|
-
maxSize: null
|
|
108
|
+
}
|
|
97
109
|
});
|
|
98
110
|
var getBase16Codec = () => codecsCore.combineCodec(getBase16Encoder(), getBase16Decoder());
|
|
99
111
|
|
|
@@ -102,29 +114,26 @@ var alphabet2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
|
102
114
|
var getBase58Encoder = () => getBaseXEncoder(alphabet2);
|
|
103
115
|
var getBase58Decoder = () => getBaseXDecoder(alphabet2);
|
|
104
116
|
var getBase58Codec = () => getBaseXCodec(alphabet2);
|
|
105
|
-
var getBaseXResliceEncoder = (alphabet4, bits) => ({
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
var getBaseXResliceEncoder = (alphabet4, bits) => codecsCore.createEncoder({
|
|
118
|
+
getSizeFromValue: (value) => Math.floor(value.length * bits / 8),
|
|
119
|
+
write(value, bytes, offset) {
|
|
108
120
|
assertValidBaseString(alphabet4, value);
|
|
109
121
|
if (value === "")
|
|
110
|
-
return
|
|
122
|
+
return offset;
|
|
111
123
|
const charIndices = [...value].map((c) => alphabet4.indexOf(c));
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
124
|
+
const reslicedBytes = reslice(charIndices, bits, 8, false);
|
|
125
|
+
bytes.set(reslicedBytes, offset);
|
|
126
|
+
return reslicedBytes.length + offset;
|
|
127
|
+
}
|
|
116
128
|
});
|
|
117
|
-
var getBaseXResliceDecoder = (alphabet4, bits) => ({
|
|
118
|
-
|
|
129
|
+
var getBaseXResliceDecoder = (alphabet4, bits) => codecsCore.createDecoder({
|
|
130
|
+
read(rawBytes, offset = 0) {
|
|
119
131
|
const bytes = offset === 0 ? rawBytes : rawBytes.slice(offset);
|
|
120
132
|
if (bytes.length === 0)
|
|
121
133
|
return ["", rawBytes.length];
|
|
122
134
|
const charIndices = reslice([...bytes], 8, bits, true);
|
|
123
135
|
return [charIndices.map((i) => alphabet4[i]).join(""), rawBytes.length];
|
|
124
|
-
}
|
|
125
|
-
description: `base${alphabet4.length}`,
|
|
126
|
-
fixedSize: null,
|
|
127
|
-
maxSize: null
|
|
136
|
+
}
|
|
128
137
|
});
|
|
129
138
|
var getBaseXResliceCodec = (alphabet4, bits) => codecsCore.combineCodec(getBaseXResliceEncoder(alphabet4, bits), getBaseXResliceDecoder(alphabet4, bits));
|
|
130
139
|
function reslice(input, inputBits, outputBits, useRemainder) {
|
|
@@ -145,35 +154,48 @@ function reslice(input, inputBits, outputBits, useRemainder) {
|
|
|
145
154
|
}
|
|
146
155
|
return output;
|
|
147
156
|
}
|
|
157
|
+
|
|
158
|
+
// src/base64.ts
|
|
159
|
+
var alphabet3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
148
160
|
var getBase64Encoder = () => {
|
|
149
161
|
{
|
|
150
|
-
return {
|
|
151
|
-
|
|
152
|
-
encode(value) {
|
|
162
|
+
return codecsCore.createEncoder({
|
|
163
|
+
getSizeFromValue: (value) => {
|
|
153
164
|
try {
|
|
154
|
-
|
|
155
|
-
return new Uint8Array(bytes);
|
|
165
|
+
return atob(value).length;
|
|
156
166
|
} catch (e2) {
|
|
157
|
-
throw new
|
|
167
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__INVALID_STRING_FOR_BASE, {
|
|
168
|
+
alphabet: alphabet3,
|
|
169
|
+
base: 64,
|
|
170
|
+
value
|
|
171
|
+
});
|
|
158
172
|
}
|
|
159
173
|
},
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
174
|
+
write(value, bytes, offset) {
|
|
175
|
+
try {
|
|
176
|
+
const bytesToAdd = atob(value).split("").map((c) => c.charCodeAt(0));
|
|
177
|
+
bytes.set(bytesToAdd, offset);
|
|
178
|
+
return bytesToAdd.length + offset;
|
|
179
|
+
} catch (e2) {
|
|
180
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__INVALID_STRING_FOR_BASE, {
|
|
181
|
+
alphabet: alphabet3,
|
|
182
|
+
base: 64,
|
|
183
|
+
value
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
});
|
|
163
188
|
}
|
|
164
189
|
};
|
|
165
190
|
var getBase64Decoder = () => {
|
|
166
191
|
{
|
|
167
|
-
return {
|
|
168
|
-
|
|
192
|
+
return codecsCore.createDecoder({
|
|
193
|
+
read(bytes, offset = 0) {
|
|
169
194
|
const slice = bytes.slice(offset);
|
|
170
195
|
const value = btoa(String.fromCharCode(...slice));
|
|
171
196
|
return [value, bytes.length];
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
fixedSize: null,
|
|
175
|
-
maxSize: null
|
|
176
|
-
};
|
|
197
|
+
}
|
|
198
|
+
});
|
|
177
199
|
}
|
|
178
200
|
};
|
|
179
201
|
var getBase64Codec = () => codecsCore.combineCodec(getBase64Encoder(), getBase64Decoder());
|
|
@@ -192,79 +214,73 @@ var o = globalThis.TextEncoder;
|
|
|
192
214
|
// src/utf8.ts
|
|
193
215
|
var getUtf8Encoder = () => {
|
|
194
216
|
let textEncoder;
|
|
195
|
-
return {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
217
|
+
return codecsCore.createEncoder({
|
|
218
|
+
getSizeFromValue: (value) => (textEncoder ||= new o()).encode(value).length,
|
|
219
|
+
write: (value, bytes, offset) => {
|
|
220
|
+
const bytesToAdd = (textEncoder ||= new o()).encode(value);
|
|
221
|
+
bytes.set(bytesToAdd, offset);
|
|
222
|
+
return offset + bytesToAdd.length;
|
|
223
|
+
}
|
|
224
|
+
});
|
|
201
225
|
};
|
|
202
226
|
var getUtf8Decoder = () => {
|
|
203
227
|
let textDecoder;
|
|
204
|
-
return {
|
|
205
|
-
|
|
206
|
-
const value = (textDecoder
|
|
228
|
+
return codecsCore.createDecoder({
|
|
229
|
+
read(bytes, offset) {
|
|
230
|
+
const value = (textDecoder ||= new e()).decode(bytes.slice(offset));
|
|
207
231
|
return [removeNullCharacters(value), bytes.length];
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
fixedSize: null,
|
|
211
|
-
maxSize: null
|
|
212
|
-
};
|
|
232
|
+
}
|
|
233
|
+
});
|
|
213
234
|
};
|
|
214
235
|
var getUtf8Codec = () => codecsCore.combineCodec(getUtf8Encoder(), getUtf8Decoder());
|
|
215
236
|
|
|
216
237
|
// src/string.ts
|
|
217
|
-
|
|
218
|
-
const size =
|
|
219
|
-
const encoding =
|
|
220
|
-
const description = options.description ?? `string(${encoding.description}; ${getSizeDescription(size)})`;
|
|
238
|
+
function getStringEncoder(config = {}) {
|
|
239
|
+
const size = config.size ?? codecsNumbers.getU32Encoder();
|
|
240
|
+
const encoding = config.encoding ?? getUtf8Encoder();
|
|
221
241
|
if (size === "variable") {
|
|
222
|
-
return
|
|
242
|
+
return encoding;
|
|
223
243
|
}
|
|
224
244
|
if (typeof size === "number") {
|
|
225
|
-
return codecsCore.fixEncoder(encoding, size
|
|
245
|
+
return codecsCore.fixEncoder(encoding, size);
|
|
226
246
|
}
|
|
227
|
-
return {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const lengthBytes = size.encode(contentBytes.length);
|
|
232
|
-
return codecsCore.mergeBytes([lengthBytes, contentBytes]);
|
|
247
|
+
return codecsCore.createEncoder({
|
|
248
|
+
getSizeFromValue: (value) => {
|
|
249
|
+
const contentSize = codecsCore.getEncodedSize(value, encoding);
|
|
250
|
+
return codecsCore.getEncodedSize(contentSize, size) + contentSize;
|
|
233
251
|
},
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
252
|
+
write: (value, bytes, offset) => {
|
|
253
|
+
const contentSize = codecsCore.getEncodedSize(value, encoding);
|
|
254
|
+
offset = size.write(contentSize, bytes, offset);
|
|
255
|
+
return encoding.write(value, bytes, offset);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
function getStringDecoder(config = {}) {
|
|
260
|
+
const size = config.size ?? codecsNumbers.getU32Decoder();
|
|
261
|
+
const encoding = config.encoding ?? getUtf8Decoder();
|
|
242
262
|
if (size === "variable") {
|
|
243
|
-
return
|
|
263
|
+
return encoding;
|
|
244
264
|
}
|
|
245
265
|
if (typeof size === "number") {
|
|
246
|
-
return codecsCore.fixDecoder(encoding, size
|
|
266
|
+
return codecsCore.fixDecoder(encoding, size);
|
|
247
267
|
}
|
|
248
|
-
return {
|
|
249
|
-
|
|
268
|
+
return codecsCore.createDecoder({
|
|
269
|
+
read: (bytes, offset = 0) => {
|
|
250
270
|
codecsCore.assertByteArrayIsNotEmptyForCodec("string", bytes, offset);
|
|
251
|
-
const [lengthBigInt, lengthOffset] = size.
|
|
271
|
+
const [lengthBigInt, lengthOffset] = size.read(bytes, offset);
|
|
252
272
|
const length = Number(lengthBigInt);
|
|
253
273
|
offset = lengthOffset;
|
|
254
274
|
const contentBytes = bytes.slice(offset, offset + length);
|
|
255
275
|
codecsCore.assertByteArrayHasEnoughBytesForCodec("string", length, contentBytes);
|
|
256
|
-
const [value, contentOffset] = encoding.
|
|
276
|
+
const [value, contentOffset] = encoding.read(contentBytes, 0);
|
|
257
277
|
offset += contentOffset;
|
|
258
278
|
return [value, offset];
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
};
|
|
265
|
-
var getStringCodec = (options = {}) => codecsCore.combineCodec(getStringEncoder(options), getStringDecoder(options));
|
|
266
|
-
function getSizeDescription(size) {
|
|
267
|
-
return typeof size === "object" ? size.description : `${size}`;
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
function getStringCodec(config = {}) {
|
|
283
|
+
return codecsCore.combineCodec(getStringEncoder(config), getStringDecoder(config));
|
|
268
284
|
}
|
|
269
285
|
|
|
270
286
|
exports.assertValidBaseString = assertValidBaseString;
|