Skip to content

Commit 9861613

Browse files
committed
feat: Uint8Array<SharedArrayBuffer> is accepted in utf8toString
1 parent f8593a2 commit 9861613

File tree

3 files changed

+56
-7
lines changed

3 files changed

+56
-7
lines changed

tests/utf8.lib.test.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ import { fromHex } from '@exodus/bytes/hex.js'
77
import { randomValues } from '@exodus/crypto/randomBytes'
88
import { describe, test } from 'node:test'
99

10+
const SharedArrayBuffer = globalThis.SharedArrayBuffer ?? ArrayBuffer
11+
const toShared = (u8) => {
12+
const res = new Uint8Array(new SharedArrayBuffer(u8.length))
13+
res.set(u8)
14+
return res
15+
}
16+
1017
// invalid bytes -> string
1118
const nonUtf8 = [
1219
{ bytes: [0, 254, 255], charcodes: [0, 0xff_fd, 0xff_fd] },
@@ -72,6 +79,8 @@ describe('utf8toString', () => {
7279
for (const method of [
7380
utf8toString,
7481
utf8toStringLoose,
82+
(x) => utf8toString(toShared(x)),
83+
(x) => utf8toStringLoose(toShared(x)),
7584
(x) => js.decode(x, false),
7685
(x) => js.decode(x, true),
7786
]) {
@@ -84,7 +93,11 @@ describe('utf8toString', () => {
8493
})
8594

8695
test('non-utf8 bytes throw in utf8toString', (t) => {
87-
for (const method of [utf8toString, (x) => js.decode(x, false)]) {
96+
for (const method of [
97+
utf8toString,
98+
(x) => utf8toString(toShared(x)),
99+
(x) => js.decode(x, false),
100+
]) {
88101
for (const { bytes } of nonUtf8) {
89102
t.assert.throws(() => method(Uint8Array.of(...bytes)))
90103

@@ -102,7 +115,11 @@ describe('utf8toString', () => {
102115
})
103116

104117
test('non-utf8 bytes get replaced in utf8toStringLoose', (t) => {
105-
for (const method of [utf8toStringLoose, (x) => js.decode(x, true)]) {
118+
for (const method of [
119+
utf8toStringLoose,
120+
(x) => utf8toStringLoose(toShared(x)),
121+
(x) => js.decode(x, true),
122+
]) {
106123
for (const { bytes, charcodes } of nonUtf8) {
107124
const res = method(Uint8Array.of(...bytes))
108125
t.assert.strictEqual(res.length, charcodes.length)
@@ -195,6 +212,7 @@ describe('random data', () => {
195212
const NativeBuffer = globalThis.Buffer && !globalThis.Buffer.TYPED_ARRAY_SUPPORT ? Buffer : null
196213
for (const u8 of pool) {
197214
const str = utf8toStringLoose(u8)
215+
t.assert.strictEqual(str, utf8toStringLoose(toShared(u8)))
198216
t.assert.strictEqual(str, js.decode(u8, true))
199217
if (textDecoder) t.assert.strictEqual(str, textDecoder.decode(u8))
200218
if (NativeBuffer) t.assert.strictEqual(str, NativeBuffer.from(u8).toString())
@@ -207,6 +225,8 @@ describe('random data', () => {
207225
for (const u8 of poolAscii) {
208226
const str = utf8toString(u8)
209227
t.assert.strictEqual(str, utf8toStringLoose(u8))
228+
t.assert.strictEqual(str, utf8toString(toShared(u8)))
229+
t.assert.strictEqual(str, utf8toStringLoose(toShared(u8)))
210230
t.assert.strictEqual(str, js.decode(u8, false))
211231
t.assert.strictEqual(str, js.decode(u8, true))
212232
if (textDecoder) t.assert.strictEqual(str, textDecoder.decode(u8))
@@ -228,11 +248,14 @@ describe('random data', () => {
228248
}
229249

230250
if (str === undefined) {
251+
t.assert.throws(() => utf8toString(toShared(u8)))
231252
t.assert.throws(() => js.decode(u8, false))
232253
if (textDecoder) t.assert.throws(() => textDecoder.decode(u8))
233254
} else {
234255
t.assert.strictEqual(str, strings[i])
235256
t.assert.strictEqual(str, utf8toStringLoose(u8))
257+
t.assert.strictEqual(str, utf8toString(toShared(u8)))
258+
t.assert.strictEqual(str, utf8toStringLoose(toShared(u8)))
236259
t.assert.strictEqual(str, js.decode(u8, false))
237260
t.assert.strictEqual(str, js.decode(u8, true))
238261
if (textDecoder) t.assert.strictEqual(str, textDecoder.decode(u8))
@@ -279,6 +302,8 @@ describe('random data', () => {
279302
const u8 = restored[i]
280303
t.assert.strictEqual(str, utf8toString(u8))
281304
t.assert.strictEqual(str, utf8toStringLoose(u8))
305+
t.assert.strictEqual(str, utf8toString(toShared(u8)))
306+
t.assert.strictEqual(str, utf8toStringLoose(toShared(u8)))
282307
t.assert.strictEqual(str, js.decode(u8, false))
283308
t.assert.strictEqual(str, js.decode(u8, true))
284309
if (textDecoder) t.assert.strictEqual(str, textDecoder.decode(u8))

tests/utf8.test.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import { fromHex } from '@exodus/bytes/hex.js'
1010
import { randomValues } from '@exodus/crypto/randomBytes'
1111
import { describe, test } from 'node:test'
1212

13+
const SharedArrayBuffer = globalThis.SharedArrayBuffer ?? ArrayBuffer
14+
const toShared = (u8) => {
15+
const res = new Uint8Array(new SharedArrayBuffer(u8.length))
16+
res.set(u8)
17+
return res
18+
}
19+
1320
// invalid bytes -> string
1421
const nonUtf8 = [
1522
{ bytes: [0, 254, 255], charcodes: [0, 0xff_fd, 0xff_fd] },
@@ -75,6 +82,8 @@ describe('utf8toString', () => {
7582
for (const method of [
7683
utf8toString,
7784
utf8toStringLoose,
85+
(x) => utf8toString(toShared(x)),
86+
(x) => utf8toStringLoose(toShared(x)),
7887
(x) => js.decode(x, false),
7988
(x) => js.decode(x, true),
8089
]) {
@@ -87,7 +96,11 @@ describe('utf8toString', () => {
8796
})
8897

8998
test('non-utf8 bytes throw in utf8toString', (t) => {
90-
for (const method of [utf8toString, (x) => js.decode(x, false)]) {
99+
for (const method of [
100+
utf8toString,
101+
(x) => utf8toString(toShared(x)),
102+
(x) => js.decode(x, false),
103+
]) {
91104
for (const { bytes } of nonUtf8) {
92105
t.assert.throws(() => method(Uint8Array.of(...bytes)))
93106

@@ -105,7 +118,11 @@ describe('utf8toString', () => {
105118
})
106119

107120
test('non-utf8 bytes get replaced in utf8toStringLoose', (t) => {
108-
for (const method of [utf8toStringLoose, (x) => js.decode(x, true)]) {
121+
for (const method of [
122+
utf8toStringLoose,
123+
(x) => utf8toStringLoose(toShared(x)),
124+
(x) => js.decode(x, true),
125+
]) {
109126
for (const { bytes, charcodes } of nonUtf8) {
110127
const res = method(Uint8Array.of(...bytes))
111128
t.assert.strictEqual(res.length, charcodes.length)
@@ -198,6 +215,7 @@ describe('random data', () => {
198215
const NativeBuffer = globalThis.Buffer && !globalThis.Buffer.TYPED_ARRAY_SUPPORT ? Buffer : null
199216
for (const u8 of pool) {
200217
const str = utf8toStringLoose(u8)
218+
t.assert.strictEqual(str, utf8toStringLoose(toShared(u8)))
201219
t.assert.strictEqual(str, js.decode(u8, true))
202220
if (textDecoder) t.assert.strictEqual(str, textDecoder.decode(u8))
203221
if (NativeBuffer) t.assert.strictEqual(str, NativeBuffer.from(u8).toString())
@@ -210,6 +228,8 @@ describe('random data', () => {
210228
for (const u8 of poolAscii) {
211229
const str = utf8toString(u8)
212230
t.assert.strictEqual(str, utf8toStringLoose(u8))
231+
t.assert.strictEqual(str, utf8toString(toShared(u8)))
232+
t.assert.strictEqual(str, utf8toStringLoose(toShared(u8)))
213233
t.assert.strictEqual(str, js.decode(u8, false))
214234
t.assert.strictEqual(str, js.decode(u8, true))
215235
if (textDecoder) t.assert.strictEqual(str, textDecoder.decode(u8))
@@ -231,11 +251,14 @@ describe('random data', () => {
231251
}
232252

233253
if (str === undefined) {
254+
t.assert.throws(() => utf8toString(toShared(u8)))
234255
t.assert.throws(() => js.decode(u8, false))
235256
if (textDecoder) t.assert.throws(() => textDecoder.decode(u8))
236257
} else {
237258
t.assert.strictEqual(str, strings[i])
238259
t.assert.strictEqual(str, utf8toStringLoose(u8))
260+
t.assert.strictEqual(str, utf8toString(toShared(u8)))
261+
t.assert.strictEqual(str, utf8toStringLoose(toShared(u8)))
239262
t.assert.strictEqual(str, js.decode(u8, false))
240263
t.assert.strictEqual(str, js.decode(u8, true))
241264
if (textDecoder) t.assert.strictEqual(str, textDecoder.decode(u8))
@@ -282,6 +305,8 @@ describe('random data', () => {
282305
const u8 = restored[i]
283306
t.assert.strictEqual(str, utf8toString(u8))
284307
t.assert.strictEqual(str, utf8toStringLoose(u8))
308+
t.assert.strictEqual(str, utf8toString(toShared(u8)))
309+
t.assert.strictEqual(str, utf8toStringLoose(toShared(u8)))
285310
t.assert.strictEqual(str, js.decode(u8, false))
286311
t.assert.strictEqual(str, js.decode(u8, true))
287312
if (textDecoder) t.assert.strictEqual(str, textDecoder.decode(u8))

utf8.d.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export function utf8fromStringLoose(
5959
* @param arr - The bytes to decode
6060
* @returns The decoded string
6161
*/
62-
export function utf8toString(arr: Uint8ArrayBuffer): string;
62+
export function utf8toString(arr: Uint8Array): string;
6363

6464
/**
6565
* Decode UTF-8 bytes to a string (loose mode)
@@ -73,5 +73,4 @@ export function utf8toString(arr: Uint8ArrayBuffer): string;
7373
* @param arr - The bytes to decode
7474
* @returns The decoded string
7575
*/
76-
export function utf8toStringLoose(arr: Uint8ArrayBuffer): string;
77-
76+
export function utf8toStringLoose(arr: Uint8Array): string;

0 commit comments

Comments
 (0)