@atproto/lex-data 0.0.4 → 0.0.5
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/CHANGELOG.md +8 -0
- package/dist/blob.d.ts.map +1 -1
- package/dist/blob.js +2 -5
- package/dist/blob.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lex-error.d.ts +17 -0
- package/dist/lex-error.d.ts.map +1 -0
- package/dist/lex-error.js +26 -0
- package/dist/lex-error.js.map +1 -0
- package/dist/lib/nodejs-buffer.d.ts +1 -0
- package/dist/lib/nodejs-buffer.d.ts.map +1 -1
- package/dist/lib/nodejs-buffer.js +1 -1
- package/dist/lib/nodejs-buffer.js.map +1 -1
- package/dist/uint8array-concat.d.ts +3 -0
- package/dist/uint8array-concat.d.ts.map +1 -0
- package/dist/uint8array-concat.js +24 -0
- package/dist/uint8array-concat.js.map +1 -0
- package/dist/uint8array-from-base64.d.ts.map +1 -1
- package/dist/uint8array-from-base64.js +1 -1
- package/dist/uint8array-from-base64.js.map +1 -1
- package/dist/uint8array.d.ts +1 -0
- package/dist/uint8array.d.ts.map +1 -1
- package/dist/uint8array.js +14 -3
- package/dist/uint8array.js.map +1 -1
- package/dist/utf8-grapheme-len.d.ts.map +1 -1
- package/dist/utf8-grapheme-len.js +2 -2
- package/dist/utf8-grapheme-len.js.map +1 -1
- package/dist/utf8-len.d.ts.map +1 -1
- package/dist/utf8-len.js +1 -1
- package/dist/utf8-len.js.map +1 -1
- package/package.json +5 -5
- package/src/blob.test.ts +83 -2
- package/src/blob.ts +2 -7
- package/src/cid.test.ts +126 -0
- package/src/index.ts +1 -0
- package/src/language.test.ts +1 -0
- package/src/lex-equals.test.ts +30 -0
- package/src/lex-error.ts +34 -0
- package/src/lex.test.ts +65 -13
- package/src/lib/nodejs-buffer.ts +2 -1
- package/src/object.test.ts +2 -0
- package/src/uint8array-concat.test.ts +197 -0
- package/src/uint8array-concat.ts +21 -0
- package/src/uint8array-from-base64.test.ts +4 -1
- package/src/uint8array-from-base64.ts +1 -1
- package/src/uint8array-to-base64.test.ts +1 -1
- package/src/uint8array.test.ts +484 -0
- package/src/uint8array.ts +14 -2
- package/src/utf8-grapheme-len.test.ts +1 -0
- package/src/utf8-grapheme-len.ts +2 -2
- package/src/utf8-len.test.ts +1 -0
- package/src/utf8-len.ts +1 -1
- package/tsconfig.tests.json +1 -1
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
import 'core-js/modules/es.uint8-array.from-base64.js'
|
|
2
|
+
import 'core-js/modules/es.uint8-array.to-base64.js'
|
|
3
|
+
|
|
4
|
+
import { describe, expect, it } from 'vitest'
|
|
5
|
+
import {
|
|
6
|
+
asUint8Array,
|
|
7
|
+
fromBase64,
|
|
8
|
+
toBase64,
|
|
9
|
+
ui8Concat,
|
|
10
|
+
ui8Equals,
|
|
11
|
+
} from './uint8array.js'
|
|
12
|
+
|
|
13
|
+
describe('toBase64', () => {
|
|
14
|
+
it('encodes empty Uint8Array', () => {
|
|
15
|
+
const encoded = toBase64(new Uint8Array(0))
|
|
16
|
+
expect(typeof encoded).toBe('string')
|
|
17
|
+
expect(encoded).toBe('')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('encodes single byte', () => {
|
|
21
|
+
const encoded = toBase64(new Uint8Array([0x4d]))
|
|
22
|
+
expect(encoded).toBe('TQ')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('encodes multiple bytes', () => {
|
|
26
|
+
const encoded = toBase64(new Uint8Array([0x4d, 0x61, 0x6e]))
|
|
27
|
+
expect(encoded).toBe('TWFu')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('encodes with default alphabet (base64)', () => {
|
|
31
|
+
const bytes = new Uint8Array([0xfb, 0xff, 0xbf])
|
|
32
|
+
const encoded = toBase64(bytes)
|
|
33
|
+
expect(encoded).toContain('+')
|
|
34
|
+
expect(encoded).toContain('/')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('encodes with base64url alphabet', () => {
|
|
38
|
+
const bytes = new Uint8Array([0xfb, 0xff, 0xbf])
|
|
39
|
+
const encoded = toBase64(bytes, 'base64url')
|
|
40
|
+
expect(encoded).toContain('-')
|
|
41
|
+
expect(encoded).toContain('_')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('handles large data', () => {
|
|
45
|
+
const bytes = new Uint8Array(10000).fill(0xaa)
|
|
46
|
+
const encoded = toBase64(bytes)
|
|
47
|
+
expect(typeof encoded).toBe('string')
|
|
48
|
+
expect(encoded.length).toBeGreaterThan(0)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('fromBase64', () => {
|
|
53
|
+
it('decodes empty string', () => {
|
|
54
|
+
const decoded = fromBase64('')
|
|
55
|
+
expect(decoded).toBeInstanceOf(Uint8Array)
|
|
56
|
+
expect(decoded.length).toBe(0)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('decodes single character', () => {
|
|
60
|
+
const decoded = fromBase64('TQ')
|
|
61
|
+
expect(decoded).toBeInstanceOf(Uint8Array)
|
|
62
|
+
expect(ui8Equals(decoded, new Uint8Array([0x4d]))).toBe(true)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('decodes multiple characters', () => {
|
|
66
|
+
const decoded = fromBase64('TWFu')
|
|
67
|
+
expect(decoded).toBeInstanceOf(Uint8Array)
|
|
68
|
+
expect(ui8Equals(decoded, new Uint8Array([0x4d, 0x61, 0x6e]))).toBe(true)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('decodes base64url alphabet', () => {
|
|
72
|
+
const decoded = fromBase64('-_-_', 'base64url')
|
|
73
|
+
expect(decoded).toBeInstanceOf(Uint8Array)
|
|
74
|
+
expect(ui8Equals(decoded, new Uint8Array([0xfb, 0xff, 0xbf]))).toBe(true)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('decodes padded base64', () => {
|
|
78
|
+
const decoded = fromBase64('TQ==')
|
|
79
|
+
expect(decoded).toBeInstanceOf(Uint8Array)
|
|
80
|
+
expect(ui8Equals(decoded, new Uint8Array([0x4d]))).toBe(true)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('decodes unpadded base64', () => {
|
|
84
|
+
const decoded = fromBase64('TQ')
|
|
85
|
+
expect(decoded).toBeInstanceOf(Uint8Array)
|
|
86
|
+
expect(ui8Equals(decoded, new Uint8Array([0x4d]))).toBe(true)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('throws on invalid base64 string', () => {
|
|
90
|
+
expect(() => fromBase64('@@@@')).toThrow()
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('handles large data', () => {
|
|
94
|
+
const bytes = new Uint8Array(10000).fill(0xbb)
|
|
95
|
+
const encoded = toBase64(bytes)
|
|
96
|
+
const decoded = fromBase64(encoded)
|
|
97
|
+
expect(ui8Equals(decoded, bytes)).toBe(true)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
describe('roundtrip toBase64 <-> fromBase64', () => {
|
|
102
|
+
it('roundtrips empty array', () => {
|
|
103
|
+
const original = new Uint8Array(0)
|
|
104
|
+
const encoded = toBase64(original)
|
|
105
|
+
const decoded = fromBase64(encoded)
|
|
106
|
+
expect(ui8Equals(decoded, original)).toBe(true)
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('roundtrips all byte values', () => {
|
|
110
|
+
const allBytes = new Uint8Array(256)
|
|
111
|
+
for (let i = 0; i < 256; i++) {
|
|
112
|
+
allBytes[i] = i
|
|
113
|
+
}
|
|
114
|
+
const encoded = toBase64(allBytes)
|
|
115
|
+
const decoded = fromBase64(encoded)
|
|
116
|
+
expect(ui8Equals(decoded, allBytes)).toBe(true)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('roundtrips with base64url alphabet', () => {
|
|
120
|
+
const original = new Uint8Array([0xfb, 0xff, 0xbf, 0x00, 0xff])
|
|
121
|
+
const encoded = toBase64(original, 'base64url')
|
|
122
|
+
const decoded = fromBase64(encoded, 'base64url')
|
|
123
|
+
expect(ui8Equals(decoded, original)).toBe(true)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('roundtrips random-like data', () => {
|
|
127
|
+
const data = new Uint8Array([
|
|
128
|
+
0x00, 0x01, 0x7f, 0x80, 0xfe, 0xff, 0x10, 0x20, 0x30, 0x40,
|
|
129
|
+
])
|
|
130
|
+
const encoded = toBase64(data)
|
|
131
|
+
const decoded = fromBase64(encoded)
|
|
132
|
+
expect(ui8Equals(decoded, data)).toBe(true)
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
describe('asUint8Array', () => {
|
|
137
|
+
describe('Uint8Array input', () => {
|
|
138
|
+
it('returns same Uint8Array instance', () => {
|
|
139
|
+
const input = new Uint8Array([1, 2, 3])
|
|
140
|
+
const result = asUint8Array(input)
|
|
141
|
+
expect(result).toBe(input)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('returns same empty Uint8Array instance', () => {
|
|
145
|
+
const input = new Uint8Array(0)
|
|
146
|
+
const result = asUint8Array(input)
|
|
147
|
+
expect(result).toBe(input)
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
describe('ArrayBuffer input', () => {
|
|
152
|
+
it('converts ArrayBuffer to Uint8Array', () => {
|
|
153
|
+
const buffer = new ArrayBuffer(4)
|
|
154
|
+
const view = new Uint8Array(buffer)
|
|
155
|
+
view.set([1, 2, 3, 4])
|
|
156
|
+
const result = asUint8Array(buffer)
|
|
157
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
158
|
+
expect(ui8Equals(result!, new Uint8Array([1, 2, 3, 4]))).toBe(true)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
it('converts empty ArrayBuffer to empty Uint8Array', () => {
|
|
162
|
+
const buffer = new ArrayBuffer(0)
|
|
163
|
+
const result = asUint8Array(buffer)
|
|
164
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
165
|
+
expect(result!.length).toBe(0)
|
|
166
|
+
})
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
describe('TypedArray (ArrayBufferView) input', () => {
|
|
170
|
+
it('converts Int8Array to Uint8Array', () => {
|
|
171
|
+
const input = new Int8Array([1, 2, 3, 4])
|
|
172
|
+
const result = asUint8Array(input)
|
|
173
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
174
|
+
expect(result!.length).toBe(4)
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('converts Int16Array to Uint8Array', () => {
|
|
178
|
+
const input = new Int16Array([1, 2])
|
|
179
|
+
const result = asUint8Array(input)
|
|
180
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
181
|
+
// Int16Array has 2 bytes per element, so 2 elements = 4 bytes
|
|
182
|
+
expect(result!.length).toBe(4)
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it('converts Int32Array to Uint8Array', () => {
|
|
186
|
+
const input = new Int32Array([1])
|
|
187
|
+
const result = asUint8Array(input)
|
|
188
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
189
|
+
// Int32Array has 4 bytes per element, so 1 element = 4 bytes
|
|
190
|
+
expect(result!.length).toBe(4)
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
it('converts Float32Array to Uint8Array', () => {
|
|
194
|
+
const input = new Float32Array([1.5])
|
|
195
|
+
const result = asUint8Array(input)
|
|
196
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
197
|
+
// Float32Array has 4 bytes per element
|
|
198
|
+
expect(result!.length).toBe(4)
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
it('converts Float64Array to Uint8Array', () => {
|
|
202
|
+
const input = new Float64Array([1.5])
|
|
203
|
+
const result = asUint8Array(input)
|
|
204
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
205
|
+
// Float64Array has 8 bytes per element
|
|
206
|
+
expect(result!.length).toBe(8)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
it('converts DataView to Uint8Array', () => {
|
|
210
|
+
const buffer = new ArrayBuffer(4)
|
|
211
|
+
const view = new DataView(buffer)
|
|
212
|
+
view.setUint8(0, 1)
|
|
213
|
+
view.setUint8(1, 2)
|
|
214
|
+
view.setUint8(2, 3)
|
|
215
|
+
view.setUint8(3, 4)
|
|
216
|
+
const result = asUint8Array(view)
|
|
217
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
218
|
+
expect(ui8Equals(result!, new Uint8Array([1, 2, 3, 4]))).toBe(true)
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
it('handles TypedArray with byteOffset', () => {
|
|
222
|
+
const buffer = new ArrayBuffer(8)
|
|
223
|
+
const fullView = new Uint8Array(buffer)
|
|
224
|
+
fullView.set([0, 0, 1, 2, 3, 4, 0, 0])
|
|
225
|
+
// Create a view with offset
|
|
226
|
+
const offsetView = new Uint8Array(buffer, 2, 4)
|
|
227
|
+
const result = asUint8Array(offsetView)
|
|
228
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
229
|
+
expect(result).toBe(offsetView) // Uint8Array returns same instance
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
it('handles Int16Array with byteOffset correctly', () => {
|
|
233
|
+
const buffer = new ArrayBuffer(8)
|
|
234
|
+
const fullView = new Uint8Array(buffer)
|
|
235
|
+
fullView.set([0, 0, 1, 0, 2, 0, 0, 0])
|
|
236
|
+
// Create Int16Array starting at byte 2, with 2 elements
|
|
237
|
+
const int16View = new Int16Array(buffer, 2, 2)
|
|
238
|
+
const result = asUint8Array(int16View)
|
|
239
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
240
|
+
expect(result!.length).toBe(4) // 2 Int16 elements = 4 bytes
|
|
241
|
+
})
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
describe('invalid inputs', () => {
|
|
245
|
+
it('returns undefined for null', () => {
|
|
246
|
+
const result = asUint8Array(null)
|
|
247
|
+
expect(result).toBeUndefined()
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('returns undefined for undefined', () => {
|
|
251
|
+
const result = asUint8Array(undefined)
|
|
252
|
+
expect(result).toBeUndefined()
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
it('returns undefined for string', () => {
|
|
256
|
+
const result = asUint8Array('hello')
|
|
257
|
+
expect(result).toBeUndefined()
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
it('returns undefined for number', () => {
|
|
261
|
+
const result = asUint8Array(42)
|
|
262
|
+
expect(result).toBeUndefined()
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
it('returns undefined for boolean', () => {
|
|
266
|
+
const result = asUint8Array(true)
|
|
267
|
+
expect(result).toBeUndefined()
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
it('returns undefined for plain object', () => {
|
|
271
|
+
const result = asUint8Array({ foo: 'bar' })
|
|
272
|
+
expect(result).toBeUndefined()
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
it('returns undefined for array', () => {
|
|
276
|
+
const result = asUint8Array([1, 2, 3])
|
|
277
|
+
expect(result).toBeUndefined()
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
it('returns undefined for function', () => {
|
|
281
|
+
const result = asUint8Array(() => {})
|
|
282
|
+
expect(result).toBeUndefined()
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
it('returns undefined for symbol', () => {
|
|
286
|
+
const result = asUint8Array(Symbol('test'))
|
|
287
|
+
expect(result).toBeUndefined()
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('returns undefined for BigInt', () => {
|
|
291
|
+
const result = asUint8Array(BigInt(42))
|
|
292
|
+
expect(result).toBeUndefined()
|
|
293
|
+
})
|
|
294
|
+
})
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
describe('ui8Equals', () => {
|
|
298
|
+
describe('equal arrays', () => {
|
|
299
|
+
it('returns true for identical arrays', () => {
|
|
300
|
+
const a = new Uint8Array([1, 2, 3])
|
|
301
|
+
const b = new Uint8Array([1, 2, 3])
|
|
302
|
+
expect(ui8Equals(a, b)).toBe(true)
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('returns true for same instance', () => {
|
|
306
|
+
const a = new Uint8Array([1, 2, 3])
|
|
307
|
+
expect(ui8Equals(a, a)).toBe(true)
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
it('returns true for empty arrays', () => {
|
|
311
|
+
const a = new Uint8Array(0)
|
|
312
|
+
const b = new Uint8Array(0)
|
|
313
|
+
expect(ui8Equals(a, b)).toBe(true)
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
it('returns true for single element arrays', () => {
|
|
317
|
+
const a = new Uint8Array([255])
|
|
318
|
+
const b = new Uint8Array([255])
|
|
319
|
+
expect(ui8Equals(a, b)).toBe(true)
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
it('returns true for arrays with all zeros', () => {
|
|
323
|
+
const a = new Uint8Array([0, 0, 0])
|
|
324
|
+
const b = new Uint8Array([0, 0, 0])
|
|
325
|
+
expect(ui8Equals(a, b)).toBe(true)
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
it('returns true for arrays with all 255s', () => {
|
|
329
|
+
const a = new Uint8Array([255, 255, 255])
|
|
330
|
+
const b = new Uint8Array([255, 255, 255])
|
|
331
|
+
expect(ui8Equals(a, b)).toBe(true)
|
|
332
|
+
})
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
describe('unequal arrays - different lengths', () => {
|
|
336
|
+
it('returns false when first is longer', () => {
|
|
337
|
+
const a = new Uint8Array([1, 2, 3, 4])
|
|
338
|
+
const b = new Uint8Array([1, 2, 3])
|
|
339
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
it('returns false when second is longer', () => {
|
|
343
|
+
const a = new Uint8Array([1, 2, 3])
|
|
344
|
+
const b = new Uint8Array([1, 2, 3, 4])
|
|
345
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
it('returns false when one is empty', () => {
|
|
349
|
+
const a = new Uint8Array([1])
|
|
350
|
+
const b = new Uint8Array(0)
|
|
351
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
it('returns false when comparing empty to non-empty', () => {
|
|
355
|
+
const a = new Uint8Array(0)
|
|
356
|
+
const b = new Uint8Array([1])
|
|
357
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
358
|
+
})
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
describe('unequal arrays - different content', () => {
|
|
362
|
+
it('returns false when first byte differs', () => {
|
|
363
|
+
const a = new Uint8Array([1, 2, 3])
|
|
364
|
+
const b = new Uint8Array([0, 2, 3])
|
|
365
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
it('returns false when middle byte differs', () => {
|
|
369
|
+
const a = new Uint8Array([1, 2, 3])
|
|
370
|
+
const b = new Uint8Array([1, 0, 3])
|
|
371
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
it('returns false when last byte differs', () => {
|
|
375
|
+
const a = new Uint8Array([1, 2, 3])
|
|
376
|
+
const b = new Uint8Array([1, 2, 0])
|
|
377
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
it('returns false for completely different arrays', () => {
|
|
381
|
+
const a = new Uint8Array([0, 0, 0])
|
|
382
|
+
const b = new Uint8Array([255, 255, 255])
|
|
383
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
it('returns false when single values differ', () => {
|
|
387
|
+
const a = new Uint8Array([0])
|
|
388
|
+
const b = new Uint8Array([1])
|
|
389
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
390
|
+
})
|
|
391
|
+
})
|
|
392
|
+
|
|
393
|
+
describe('edge cases', () => {
|
|
394
|
+
it('handles boundary byte values', () => {
|
|
395
|
+
const a = new Uint8Array([0x00, 0x7f, 0x80, 0xff])
|
|
396
|
+
const b = new Uint8Array([0x00, 0x7f, 0x80, 0xff])
|
|
397
|
+
expect(ui8Equals(a, b)).toBe(true)
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
it('detects difference at boundary values', () => {
|
|
401
|
+
const a = new Uint8Array([0x7f])
|
|
402
|
+
const b = new Uint8Array([0x80])
|
|
403
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
it('handles large arrays efficiently', () => {
|
|
407
|
+
const size = 100000
|
|
408
|
+
const a = new Uint8Array(size).fill(0xaa)
|
|
409
|
+
const b = new Uint8Array(size).fill(0xaa)
|
|
410
|
+
expect(ui8Equals(a, b)).toBe(true)
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
it('detects single byte difference in large arrays', () => {
|
|
414
|
+
const size = 100000
|
|
415
|
+
const a = new Uint8Array(size).fill(0xaa)
|
|
416
|
+
const b = new Uint8Array(size).fill(0xaa)
|
|
417
|
+
b[size - 1] = 0xbb // Difference at the end
|
|
418
|
+
expect(ui8Equals(a, b)).toBe(false)
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
it('compares subarrays correctly', () => {
|
|
422
|
+
const full = new Uint8Array([0, 1, 2, 3, 4, 5])
|
|
423
|
+
const sub1 = full.subarray(1, 4) // [1, 2, 3]
|
|
424
|
+
const sub2 = new Uint8Array([1, 2, 3])
|
|
425
|
+
expect(ui8Equals(sub1, sub2)).toBe(true)
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
it('detects difference in subarrays', () => {
|
|
429
|
+
const full = new Uint8Array([0, 1, 2, 3, 4, 5])
|
|
430
|
+
const sub1 = full.subarray(1, 4) // [1, 2, 3]
|
|
431
|
+
const sub2 = new Uint8Array([1, 2, 4]) // Different last byte
|
|
432
|
+
expect(ui8Equals(sub1, sub2)).toBe(false)
|
|
433
|
+
})
|
|
434
|
+
})
|
|
435
|
+
})
|
|
436
|
+
|
|
437
|
+
describe('ui8Concat', () => {
|
|
438
|
+
it('concatenates empty array', () => {
|
|
439
|
+
const result = ui8Concat([])
|
|
440
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
441
|
+
expect(result.length).toBe(0)
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
it('concatenates single array', () => {
|
|
445
|
+
const input = new Uint8Array([1, 2, 3])
|
|
446
|
+
const result = ui8Concat([input])
|
|
447
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
448
|
+
expect(ui8Equals(result, input)).toBe(true)
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
it('concatenates two arrays', () => {
|
|
452
|
+
const a = new Uint8Array([1, 2])
|
|
453
|
+
const b = new Uint8Array([3, 4])
|
|
454
|
+
const result = ui8Concat([a, b])
|
|
455
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
456
|
+
expect(ui8Equals(result, new Uint8Array([1, 2, 3, 4]))).toBe(true)
|
|
457
|
+
})
|
|
458
|
+
|
|
459
|
+
it('concatenates multiple arrays', () => {
|
|
460
|
+
const arrays = [
|
|
461
|
+
new Uint8Array([1]),
|
|
462
|
+
new Uint8Array([2, 3]),
|
|
463
|
+
new Uint8Array([4, 5, 6]),
|
|
464
|
+
]
|
|
465
|
+
const result = ui8Concat(arrays)
|
|
466
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
467
|
+
expect(ui8Equals(result, new Uint8Array([1, 2, 3, 4, 5, 6]))).toBe(true)
|
|
468
|
+
})
|
|
469
|
+
|
|
470
|
+
it('handles empty arrays in input', () => {
|
|
471
|
+
const a = new Uint8Array(0)
|
|
472
|
+
const b = new Uint8Array([1, 2])
|
|
473
|
+
const c = new Uint8Array(0)
|
|
474
|
+
const result = ui8Concat([a, b, c])
|
|
475
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
476
|
+
expect(ui8Equals(result, new Uint8Array([1, 2]))).toBe(true)
|
|
477
|
+
})
|
|
478
|
+
|
|
479
|
+
it('handles all empty arrays', () => {
|
|
480
|
+
const result = ui8Concat([new Uint8Array(0), new Uint8Array(0)])
|
|
481
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
482
|
+
expect(result.length).toBe(0)
|
|
483
|
+
})
|
|
484
|
+
})
|
package/src/uint8array.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Base64Alphabet } from './uint8array-base64.js'
|
|
2
|
+
import { ui8ConcatNode, ui8ConcatPonyfill } from './uint8array-concat.js'
|
|
2
3
|
import {
|
|
3
4
|
fromBase64Native,
|
|
4
5
|
fromBase64Node,
|
|
@@ -25,7 +26,10 @@ export type { Base64Alphabet }
|
|
|
25
26
|
export const toBase64: (
|
|
26
27
|
bytes: Uint8Array,
|
|
27
28
|
alphabet?: Base64Alphabet,
|
|
28
|
-
) => string =
|
|
29
|
+
) => string =
|
|
30
|
+
/* v8 ignore next -- @preserve */ toBase64Native ??
|
|
31
|
+
/* v8 ignore next -- @preserve */ toBase64Node ??
|
|
32
|
+
/* v8 ignore next -- @preserve */ toBase64Ponyfill
|
|
29
33
|
|
|
30
34
|
/**
|
|
31
35
|
* Decodes a base64 string into a Uint8Array. This function supports both padded
|
|
@@ -37,8 +41,12 @@ export const toBase64: (
|
|
|
37
41
|
export const fromBase64: (
|
|
38
42
|
b64: string,
|
|
39
43
|
alphabet?: Base64Alphabet,
|
|
40
|
-
) => Uint8Array =
|
|
44
|
+
) => Uint8Array =
|
|
45
|
+
/* v8 ignore next -- @preserve */ fromBase64Native ??
|
|
46
|
+
/* v8 ignore next -- @preserve */ fromBase64Node ??
|
|
47
|
+
/* v8 ignore next -- @preserve */ fromBase64Ponyfill
|
|
41
48
|
|
|
49
|
+
/* v8 ignore next -- @preserve */
|
|
42
50
|
if (toBase64 === toBase64Ponyfill || fromBase64 === fromBase64Ponyfill) {
|
|
43
51
|
/*#__PURE__*/
|
|
44
52
|
console.warn(
|
|
@@ -84,3 +92,7 @@ export function ui8Equals(a: Uint8Array, b: Uint8Array): boolean {
|
|
|
84
92
|
|
|
85
93
|
return true
|
|
86
94
|
}
|
|
95
|
+
|
|
96
|
+
export const ui8Concat =
|
|
97
|
+
/* v8 ignore next -- @preserve */ ui8ConcatNode ??
|
|
98
|
+
/* v8 ignore next -- @preserve */ ui8ConcatPonyfill
|
package/src/utf8-grapheme-len.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { countGraphemes } from 'unicode-segmenter/grapheme'
|
|
|
6
6
|
const segmenter =
|
|
7
7
|
'Segmenter' in Intl && typeof Intl.Segmenter === 'function'
|
|
8
8
|
? /*#__PURE__*/ new Intl.Segmenter()
|
|
9
|
-
: null
|
|
9
|
+
: /* v8 ignore next -- @preserve */ null
|
|
10
10
|
|
|
11
11
|
export const graphemeLenNative = segmenter
|
|
12
12
|
? function graphemeLenNative(str: string): number {
|
|
@@ -14,7 +14,7 @@ export const graphemeLenNative = segmenter
|
|
|
14
14
|
for (const _ of segmenter.segment(str)) length++
|
|
15
15
|
return length
|
|
16
16
|
}
|
|
17
|
-
: null
|
|
17
|
+
: /* v8 ignore next -- @preserve */ null
|
|
18
18
|
|
|
19
19
|
export function graphemeLenPonyfill(str: string): number {
|
|
20
20
|
return countGraphemes(str)
|
package/src/utf8-len.test.ts
CHANGED
package/src/utf8-len.ts
CHANGED
|
@@ -8,7 +8,7 @@ export const utf8LenNode = NodeJSBuffer
|
|
|
8
8
|
? function utf8LenNode(string: string): number {
|
|
9
9
|
return NodeJSBuffer!.byteLength(string, 'utf8')
|
|
10
10
|
}
|
|
11
|
-
: null
|
|
11
|
+
: /* v8 ignore next -- @preserve */ null
|
|
12
12
|
|
|
13
13
|
export function utf8LenCompute(string: string): number {
|
|
14
14
|
// The code below is similar to TextEncoder's implementation of UTF-8
|
package/tsconfig.tests.json
CHANGED