diff --git a/array.d.ts b/array.d.ts index 79390fc..67f036f 100644 --- a/array.d.ts +++ b/array.d.ts @@ -45,12 +45,7 @@ export type Uint32ArrayBuffer = ReturnType; /** * Output format for typed array conversions */ -export type OutputFormat = 'uint8' | 'buffer'; - -/** - * Output format for typed array copy conversions - */ -export type OutputCopyFormat = 'uint8' | 'arraybuffer' | 'buffer'; +export type OutputFormat = 'uint8' | 'arraybuffer' | 'buffer'; /** * Create a view of a TypedArray in the specified format (`'uint8'` or `'buffer'`) @@ -68,7 +63,7 @@ export type OutputCopyFormat = 'uint8' | 'arraybuffer' | 'buffer'; */ export function typedView(arr: ArrayBufferView, format: 'uint8'): Uint8Array; export function typedView(arr: ArrayBufferView, format: 'buffer'): Buffer; -export function typedView(arr: ArrayBufferView, format: OutputFormat): Uint8Array | Buffer; +export function typedView(arr: ArrayBufferView, format: 'uint8' | 'buffer'): Uint8Array | Buffer; /** * Create a copy of TypedArray underlying bytes in the specified format (`'uint8'`, `'buffer'`, or `'arraybuffer'`) @@ -91,4 +86,4 @@ export function typedView(arr: ArrayBufferView, format: OutputFormat): Uint8Arra export function typedCopyBytes(arr: ArrayBufferView, format: 'uint8'): Uint8Array; export function typedCopyBytes(arr: ArrayBufferView, format: 'arraybuffer'): ArrayBuffer; export function typedCopyBytes(arr: ArrayBufferView, format: 'buffer'): Buffer; -export function typedCopyBytes(arr: ArrayBufferView, format: OutputCopyFormat): Uint8Array | ArrayBuffer | Buffer; +export function typedCopyBytes(arr: ArrayBufferView, format: OutputFormat): Uint8Array | ArrayBuffer | Buffer; diff --git a/base32.d.ts b/base32.d.ts index 3642ff3..b6e68bc 100644 --- a/base32.d.ts +++ b/base32.d.ts @@ -77,8 +77,9 @@ export function toBase32crockford(arr: Uint8Array, options?: ToBase32Options): s * @returns The decoded bytes */ export function fromBase32(string: string, options?: FromBase32Options & { format?: 'uint8' }): Uint8ArrayBuffer; +export function fromBase32(string: string, options: FromBase32Options & { format: 'arraybuffer' }): ArrayBuffer; export function fromBase32(string: string, options: FromBase32Options & { format: 'buffer' }): Buffer; -export function fromBase32(string: string, options?: FromBase32Options): Uint8ArrayBuffer | Buffer; +export function fromBase32(string: string, options?: FromBase32Options): Uint8ArrayBuffer | ArrayBuffer | Buffer; /** * Decode a base32hex string to bytes @@ -90,8 +91,9 @@ export function fromBase32(string: string, options?: FromBase32Options): Uint8Ar * @returns The decoded bytes */ export function fromBase32hex(string: string, options?: FromBase32Options & { format?: 'uint8' }): Uint8ArrayBuffer; +export function fromBase32hex(string: string, options: FromBase32Options & { format: 'arraybuffer' }): ArrayBuffer; export function fromBase32hex(string: string, options: FromBase32Options & { format: 'buffer' }): Buffer; -export function fromBase32hex(string: string, options?: FromBase32Options): Uint8ArrayBuffer | Buffer; +export function fromBase32hex(string: string, options?: FromBase32Options): Uint8ArrayBuffer | ArrayBuffer | Buffer; /** * Decode a Crockford base32 string to bytes @@ -105,5 +107,6 @@ export function fromBase32hex(string: string, options?: FromBase32Options): Uint * @returns The decoded bytes */ export function fromBase32crockford(string: string, options?: FromBase32Options & { format?: 'uint8' }): Uint8ArrayBuffer; +export function fromBase32crockford(string: string, options: FromBase32Options & { format: 'arraybuffer' }): ArrayBuffer; export function fromBase32crockford(string: string, options: FromBase32Options & { format: 'buffer' }): Buffer; -export function fromBase32crockford(string: string, options?: FromBase32Options): Uint8ArrayBuffer | Buffer; +export function fromBase32crockford(string: string, options?: FromBase32Options): Uint8ArrayBuffer | ArrayBuffer | Buffer; diff --git a/base58.d.ts b/base58.d.ts index f4297a0..fa22950 100644 --- a/base58.d.ts +++ b/base58.d.ts @@ -35,8 +35,9 @@ export function toBase58(arr: Uint8Array): string; * @returns The decoded bytes */ export function fromBase58(string: string, format?: 'uint8'): Uint8ArrayBuffer; +export function fromBase58(string: string, format: 'arraybuffer'): ArrayBuffer; export function fromBase58(string: string, format: 'buffer'): Buffer; -export function fromBase58(string: string, format?: OutputFormat): Uint8ArrayBuffer | Buffer; +export function fromBase58(string: string, format?: OutputFormat): Uint8ArrayBuffer | ArrayBuffer | Buffer; /** * Encode a `Uint8Array` to a base58 string using XRP alphabet @@ -58,5 +59,6 @@ export function toBase58xrp(arr: Uint8Array): string; * @returns The decoded bytes */ export function fromBase58xrp(string: string, format?: 'uint8'): Uint8ArrayBuffer; +export function fromBase58xrp(string: string, format: 'arraybuffer'): ArrayBuffer; export function fromBase58xrp(string: string, format: 'buffer'): Buffer; -export function fromBase58xrp(string: string, format?: OutputFormat): Uint8ArrayBuffer | Buffer; +export function fromBase58xrp(string: string, format?: OutputFormat): Uint8ArrayBuffer | ArrayBuffer | Buffer; diff --git a/base58check.d.ts b/base58check.d.ts index 9e6c29a..6fa6f87 100644 --- a/base58check.d.ts +++ b/base58check.d.ts @@ -46,8 +46,9 @@ export interface Base58CheckAsync { * @returns A Promise that resolves to the decoded bytes */ decode(string: string, format?: 'uint8'): Promise; + decode(string: string, format: 'arraybuffer'): Promise; decode(string: string, format: 'buffer'): Promise; - decode(string: string, format?: OutputFormat): Promise; + decode(string: string, format?: OutputFormat): Promise; } /** @@ -70,8 +71,9 @@ export interface Base58CheckSync extends Base58CheckAsync { * @returns The decoded bytes */ decodeSync(string: string, format?: 'uint8'): Uint8ArrayBuffer; + decodeSync(string: string, format: 'arraybuffer'): ArrayBuffer; decodeSync(string: string, format: 'buffer'): Buffer; - decodeSync(string: string, format?: OutputFormat): Uint8ArrayBuffer | Buffer; + decodeSync(string: string, format?: OutputFormat): Uint8ArrayBuffer | ArrayBuffer | Buffer; } /** @@ -104,8 +106,9 @@ export function toBase58check(arr: Uint8Array): Promise; * @returns A Promise that resolves to the decoded bytes */ export function fromBase58check(string: string, format?: 'uint8'): Promise; +export function fromBase58check(string: string, format: 'arraybuffer'): Promise; export function fromBase58check(string: string, format: 'buffer'): Promise; -export function fromBase58check(string: string, format?: OutputFormat): Promise; +export function fromBase58check(string: string, format?: OutputFormat): Promise; /** * Encode bytes to base58check string synchronously @@ -127,5 +130,6 @@ export function toBase58checkSync(arr: Uint8Array): string; * @returns The decoded bytes */ export function fromBase58checkSync(string: string, format?: 'uint8'): Uint8ArrayBuffer; +export function fromBase58checkSync(string: string, format: 'arraybuffer'): ArrayBuffer; export function fromBase58checkSync(string: string, format: 'buffer'): Buffer; -export function fromBase58checkSync(string: string, format?: OutputFormat): Uint8ArrayBuffer | Buffer; +export function fromBase58checkSync(string: string, format?: OutputFormat): Uint8ArrayBuffer | ArrayBuffer | Buffer; diff --git a/base64.d.ts b/base64.d.ts index f4f2fa0..8779c84 100644 --- a/base64.d.ts +++ b/base64.d.ts @@ -69,8 +69,9 @@ export function toBase64url(arr: Uint8Array, options?: ToBase64Options): string; * @returns The decoded bytes */ export function fromBase64(string: string, options?: FromBase64Options & { format?: 'uint8' }): Uint8ArrayBuffer; +export function fromBase64(string: string, options: FromBase64Options & { format: 'arraybuffer' }): ArrayBuffer; export function fromBase64(string: string, options: FromBase64Options & { format: 'buffer' }): Buffer; -export function fromBase64(string: string, options?: FromBase64Options): Uint8ArrayBuffer | Buffer; +export function fromBase64(string: string, options?: FromBase64Options): Uint8ArrayBuffer | ArrayBuffer | Buffer; /** * Decode a base64url string to bytes @@ -82,8 +83,9 @@ export function fromBase64(string: string, options?: FromBase64Options): Uint8Ar * @returns The decoded bytes */ export function fromBase64url(string: string, options?: FromBase64Options & { format?: 'uint8' }): Uint8ArrayBuffer; +export function fromBase64url(string: string, options: FromBase64Options & { format: 'arraybuffer' }): ArrayBuffer; export function fromBase64url(string: string, options: FromBase64Options & { format: 'buffer' }): Buffer; -export function fromBase64url(string: string, options?: FromBase64Options): Uint8ArrayBuffer | Buffer; +export function fromBase64url(string: string, options?: FromBase64Options): Uint8ArrayBuffer | ArrayBuffer | Buffer; /** * Decode either base64 or base64url string to bytes @@ -95,5 +97,6 @@ export function fromBase64url(string: string, options?: FromBase64Options): Uint * @returns The decoded bytes */ export function fromBase64any(string: string, options?: FromBase64Options & { format?: 'uint8' }): Uint8ArrayBuffer; +export function fromBase64any(string: string, options: FromBase64Options & { format: 'arraybuffer' }): ArrayBuffer; export function fromBase64any(string: string, options: FromBase64Options & { format: 'buffer' }): Buffer; -export function fromBase64url(string: string, options?: FromBase64Options): Uint8ArrayBuffer | Buffer; +export function fromBase64url(string: string, options?: FromBase64Options): Uint8ArrayBuffer | ArrayBuffer | Buffer; diff --git a/bigint.d.ts b/bigint.d.ts index 3a50dfa..7df9797 100644 --- a/bigint.d.ts +++ b/bigint.d.ts @@ -34,8 +34,9 @@ export interface FromBigIntOptions { * @returns The converted bytes in big-endian format */ export function fromBigInt(bigint: bigint, options: { length: number; format?: 'uint8' }): Uint8ArrayBuffer; +export function fromBigInt(bigint: bigint, options: { length: number; format: 'arraybuffer' }): ArrayBuffer; export function fromBigInt(bigint: bigint, options: { length: number; format: 'buffer' }): Buffer; -export function fromBigInt(bigint: bigint, options: FromBigIntOptions): Uint8ArrayBuffer | Buffer; +export function fromBigInt(bigint: bigint, options: FromBigIntOptions): Uint8ArrayBuffer | ArrayBuffer | Buffer; /** * Convert a Uint8Array or Buffer to a BigInt diff --git a/fallback/_utils.js b/fallback/_utils.js index 0de7f70..b662ce4 100644 --- a/fallback/_utils.js +++ b/fallback/_utils.js @@ -25,6 +25,9 @@ export function fromUint8(arr, format) { case 'uint8': if (arr.constructor !== Uint8Array) throw new Error('Unexpected') return arr + case 'arraybuffer': + if (arr.byteLength !== arr.buffer.byteLength) throw new Error('Unexpected') + return arr.buffer case 'buffer': if (arr.length <= 64) return Buffer.from(arr) return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength) @@ -43,6 +46,8 @@ export function fromBuffer(arr, format) { } return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength) + case 'arraybuffer': + return fromBuffer(arr, 'uint8').buffer case 'buffer': if (arr.constructor !== Buffer) throw new Error('Unexpected') return arr diff --git a/hex.d.ts b/hex.d.ts index dbd29e6..863a308 100644 --- a/hex.d.ts +++ b/hex.d.ts @@ -31,5 +31,6 @@ export function toHex(arr: Uint8Array): string; * @returns The decoded bytes */ export function fromHex(string: string, format?: 'uint8'): Uint8ArrayBuffer; +export function fromHex(string: string, format: 'arraybuffer'): ArrayBuffer; export function fromHex(string: string, format: 'buffer'): Buffer; -export function fromHex(string: string, format?: OutputFormat): Uint8ArrayBuffer | Buffer; +export function fromHex(string: string, format?: OutputFormat): Uint8ArrayBuffer | ArrayBuffer | Buffer; diff --git a/tests/base32.test.js b/tests/base32.test.js index 4a1ed94..632db3d 100644 --- a/tests/base32.test.js +++ b/tests/base32.test.js @@ -23,7 +23,9 @@ const pool = raw.map((uint8) => { const hex = buffer.toString('hex') const shared = new Uint8Array(new SharedArrayBuffer(uint8.length)) shared.set(uint8) - return { uint8, shared, buffer, hex, base32, base32padded, base32hex, base32hexPadded } + const ab = uint8.buffer + if (ab.byteLength !== uint8.byteLength) throw new Error('Unexpected pooled Uint8Array') + return { uint8, ab, shared, buffer, hex, base32, base32padded, base32hex, base32hexPadded } }) describe('toBase32', () => { @@ -110,7 +112,7 @@ describe('fromBase32', () => { t.assert.throws(() => fromBase32hex(input.toUpperCase())) t.assert.throws(() => fromBase32(input.toLowerCase())) t.assert.throws(() => fromBase32hex(input.toLowerCase())) - for (const format of ['uint8', 'buffer', 'hex']) { + for (const format of ['uint8', 'buffer', 'arraybuffer', 'hex']) { t.assert.throws(() => fromBase32(input, { format })) t.assert.throws(() => fromBase32hex(input, { format })) } @@ -145,9 +147,18 @@ describe('fromBase32', () => { }) test('buffer', (t) => { - for (const { base32, base32hex, buffer } of pool) { + for (const { base32, base32padded, base32hex, buffer } of pool) { t.assert.deepStrictEqual(fromBase32(base32, { format: 'buffer' }), buffer) + t.assert.deepStrictEqual(fromBase32(base32padded, { format: 'buffer' }), buffer) t.assert.deepStrictEqual(fromBase32hex(base32hex, { format: 'buffer' }), buffer) } }) + + test('arraybuffer', (t) => { + for (const { base32, base32padded, base32hex, ab } of pool) { + t.assert.deepStrictEqual(fromBase32(base32, { format: 'arraybuffer' }), ab) + t.assert.deepStrictEqual(fromBase32(base32padded, { format: 'arraybuffer' }), ab) + t.assert.deepStrictEqual(fromBase32hex(base32hex, { format: 'arraybuffer' }), ab) + } + }) }) diff --git a/tests/base58.test.js b/tests/base58.test.js index 5fde326..ae23e38 100644 --- a/tests/base58.test.js +++ b/tests/base58.test.js @@ -134,18 +134,22 @@ test('sizes roundtrip, static data + types', (t) => { const zerosBase58 = toBase58(zeros) t.assert.deepStrictEqual(fromBase58(zerosBase58), zeros, `[0] x${size}`) t.assert.deepStrictEqual(fromBase58(zerosBase58, 'buffer'), Buffer.from(zeros)) + t.assert.deepStrictEqual(fromBase58(zerosBase58, 'arraybuffer'), zeros.buffer) const ones = new Uint8Array(size).fill(1) const onesBase58 = toBase58(ones) t.assert.deepStrictEqual(fromBase58(onesBase58), ones, `[1] x${size}`) t.assert.deepStrictEqual(fromBase58(onesBase58, 'buffer'), Buffer.from(ones)) + t.assert.deepStrictEqual(fromBase58(onesBase58, 'arraybuffer'), ones.buffer) const mid = new Uint8Array(size).fill(42) const midBase58 = toBase58(mid) t.assert.deepStrictEqual(fromBase58(midBase58), mid, `[42] x${size}`) t.assert.deepStrictEqual(fromBase58(midBase58, 'buffer'), Buffer.from(mid)) + t.assert.deepStrictEqual(fromBase58(midBase58, 'arraybuffer'), mid.buffer) const max = new Uint8Array(size).fill(255) const maxBase58 = toBase58(max) t.assert.deepStrictEqual(fromBase58(maxBase58), max, `[255] x${size}`) t.assert.deepStrictEqual(fromBase58(maxBase58, 'buffer'), Buffer.from(max)) + t.assert.deepStrictEqual(fromBase58(maxBase58, 'arraybuffer'), max.buffer) } }) @@ -191,7 +195,7 @@ test('fromBase58 returns non-pooled Uint8Array instances', (t) => { t.assert.ok(tracked.length > 1000) for (const u8 of tracked) { - if (Buffer.isBuffer(u8)) continue + if (Buffer.isBuffer(u8) || u8 instanceof ArrayBuffer) continue t.assert.strictEqual(u8.byteLength, u8.buffer.byteLength) } }) diff --git a/tests/base58check.test.js b/tests/base58check.test.js index 36de9c5..6b08b47 100644 --- a/tests/base58check.test.js +++ b/tests/base58check.test.js @@ -47,18 +47,22 @@ test('sizes roundtrip, static data + types', (t) => { const zerosBase58check = toBase58checkSync(zeros) t.assert.deepStrictEqual(fromBase58checkSync(zerosBase58check), zeros, `[0] x${size}`) t.assert.deepStrictEqual(fromBase58checkSync(zerosBase58check, 'buffer'), Buffer.from(zeros)) + t.assert.deepStrictEqual(fromBase58checkSync(zerosBase58check, 'arraybuffer'), zeros.buffer) const ones = new Uint8Array(size).fill(1) const onesBase58check = toBase58checkSync(ones) t.assert.deepStrictEqual(fromBase58checkSync(onesBase58check), ones, `[1] x${size}`) t.assert.deepStrictEqual(fromBase58checkSync(onesBase58check, 'buffer'), Buffer.from(ones)) + t.assert.deepStrictEqual(fromBase58checkSync(onesBase58check, 'arraybuffer'), ones.buffer) const mid = new Uint8Array(size).fill(42) const midBase58check = toBase58checkSync(mid) t.assert.deepStrictEqual(fromBase58checkSync(midBase58check), mid, `[42] x${size}`) t.assert.deepStrictEqual(fromBase58checkSync(midBase58check, 'buffer'), Buffer.from(mid)) + t.assert.deepStrictEqual(fromBase58checkSync(midBase58check, 'arraybuffer'), mid.buffer) const max = new Uint8Array(size).fill(255) const maxBase58check = toBase58checkSync(max) t.assert.deepStrictEqual(fromBase58checkSync(maxBase58check), max, `[255] x${size}`) t.assert.deepStrictEqual(fromBase58checkSync(maxBase58check, 'buffer'), Buffer.from(max)) + t.assert.deepStrictEqual(fromBase58checkSync(maxBase58check, 'arraybuffer'), max.buffer) } }) @@ -104,7 +108,7 @@ test('fromBase58check returns non-pooled Uint8Array instances', (t) => { t.assert.ok(tracked.length > 1000) for (const u8 of tracked) { - if (Buffer.isBuffer(u8)) continue + if (Buffer.isBuffer(u8) || u8 instanceof ArrayBuffer) continue t.assert.strictEqual(u8.byteLength, u8.buffer.byteLength) } }) diff --git a/tests/base64.test.js b/tests/base64.test.js index 30cf743..60c8ec2 100644 --- a/tests/base64.test.js +++ b/tests/base64.test.js @@ -25,7 +25,9 @@ const pool = raw.map((uint8) => { const hex = buffer.toString('hex') const shared = new Uint8Array(new SharedArrayBuffer(uint8.length)) shared.set(uint8) - return { uint8, shared, buffer, hex, base64, base64nopad, base64url, base64urlPadded } + const ab = uint8.buffer + if (ab.byteLength !== uint8.byteLength) throw new Error('Unexpected pooled Uint8Array') + return { uint8, ab, shared, buffer, hex, base64, base64nopad, base64url, base64urlPadded } }) describe('toBase64', () => { @@ -114,7 +116,7 @@ describe('fromBase64', () => { ]) { t.assert.throws(() => fromBase64(input)) t.assert.throws(() => fromBase64url(input)) - for (const format of ['uint8', 'buffer', 'hex']) { + for (const format of ['uint8', 'arraybuffer', 'buffer', 'hex']) { t.assert.throws(() => fromBase64(input, { format })) t.assert.throws(() => fromBase64url(input, { format })) } @@ -162,6 +164,13 @@ describe('fromBase64', () => { } }) + test('arraybuffer', (t) => { + for (const { base64, base64url, ab } of pool) { + t.assert.deepStrictEqual(fromBase64(base64, { format: 'arraybuffer' }), ab) + t.assert.deepStrictEqual(fromBase64url(base64url, { format: 'arraybuffer' }), ab) + } + }) + test('fallback', (t) => { for (const { base64, base64nopad, base64url, base64urlPadded, uint8 } of pool) { t.assert.deepStrictEqual(js.fromBase64(base64, false), uint8) diff --git a/tests/bigint.test.js b/tests/bigint.test.js index a830002..448b2e8 100644 --- a/tests/bigint.test.js +++ b/tests/bigint.test.js @@ -13,7 +13,9 @@ const pool = raw.map((uint8) => { const buffer = Buffer.from(uint8) const shared = new Uint8Array(new SharedArrayBuffer(uint8.length)) shared.set(uint8) - return { uint8, shared, buffer, big: BigInt(`0x${buffer.toString('hex') || '0'}`) } + const ab = uint8.buffer + if (ab.byteLength !== uint8.byteLength) throw new Error('Unexpected pooled Uint8Array') + return { uint8, ab, shared, buffer, big: BigInt(`0x${buffer.toString('hex') || '0'}`) } }) const VALID = [ @@ -67,15 +69,18 @@ describe('fromBigInt', () => { test('length and format', (t) => { t.assert.throws(() => fromBigInt(0n)) t.assert.throws(() => fromBigInt(0n, { format: 'uint8' })) + t.assert.throws(() => fromBigInt(0n, { format: 'arraybuffer' })) t.assert.throws(() => fromBigInt(0n, { format: 'buffer' })) - t.assert.deepStrictEqual(fromBigInt(0n, { length: 1 }), Uint8Array.of(0)) - t.assert.deepStrictEqual(fromBigInt(0n, { length: 1, format: 'uint8' }), Uint8Array.of(0)) - t.assert.deepStrictEqual(fromBigInt(0n, { length: 1, format: 'buffer' }), Buffer.of(0)) - - t.assert.deepStrictEqual(fromBigInt(0n, { length: 2 }), Uint8Array.of(0, 0)) - t.assert.deepStrictEqual(fromBigInt(0n, { length: 2, format: 'uint8' }), Uint8Array.of(0, 0)) - t.assert.deepStrictEqual(fromBigInt(0n, { length: 2, format: 'buffer' }), Buffer.of(0, 0)) + for (const l of [1, 2, 3, 10, 20, 100, 1025]) { + t.assert.deepStrictEqual(fromBigInt(0n, { length: l }), new Uint8Array(l)) + t.assert.deepStrictEqual(fromBigInt(0n, { length: l, format: 'uint8' }), new Uint8Array(l)) + t.assert.deepStrictEqual( + fromBigInt(0n, { length: l, format: 'arraybuffer' }), + new ArrayBuffer(l) + ) + t.assert.deepStrictEqual(fromBigInt(0n, { length: l, format: 'buffer' }), Buffer.alloc(l)) + } t.assert.throws(() => fromBigInt(0n, { length: 1, format: 'invalid' })) t.assert.throws(() => fromBigInt(0n, { length: 2, format: 'invalid' })) @@ -83,6 +88,7 @@ describe('fromBigInt', () => { for (const length of [0, null, undefined, '', '0', '1']) { t.assert.throws(() => fromBigInt(0n, { length })) t.assert.throws(() => fromBigInt(0n, { length, format: 'uint8' })) + t.assert.throws(() => fromBigInt(0n, { length, format: 'arraybuffer' })) t.assert.throws(() => fromBigInt(0n, { length, format: 'buffer' })) } }) @@ -92,7 +98,7 @@ describe('fromBigInt', () => { t.assert.throws(() => fromBigInt(input)) t.assert.throws(() => fromBigInt(input, { length: 1 })) t.assert.throws(() => fromBigInt(input, { length: 10 })) - for (const format of ['uint8', 'buffer', 'hex']) { + for (const format of ['uint8', 'arraybuffer', 'buffer', 'hex']) { t.assert.throws(() => fromBigInt(input, { format })) t.assert.throws(() => fromBigInt(input, { length: 1, format })) t.assert.throws(() => fromBigInt(input, { length: 10, format })) @@ -106,6 +112,7 @@ describe('fromBigInt', () => { if (length === 0) continue t.assert.deepStrictEqual(fromBigInt(big, { length }), uint8) t.assert.deepStrictEqual(fromBigInt(big, { length, format: 'uint8' }), uint8) + t.assert.deepStrictEqual(fromBigInt(big, { length, format: 'arraybuffer' }), uint8.buffer) t.assert.deepStrictEqual(fromBigInt(big, { length, format: 'buffer' }), Buffer.from(uint8)) if (uint8[0] > 0) { t.assert.throws(() => fromBigInt(big, { length: length - 1 })) @@ -116,12 +123,13 @@ describe('fromBigInt', () => { }) test('random', (t) => { - for (const { big, uint8, buffer } of pool) { + for (const { big, uint8, ab, buffer } of pool) { const length = uint8.length if (length === 0) continue t.assert.deepStrictEqual(fromBigInt(big, { length }), uint8) - t.assert.deepStrictEqual(fromBigInt(big, { length, format: 'uint8' }, 'uint8'), uint8) - t.assert.deepStrictEqual(fromBigInt(big, { length, format: 'buffer' }, 'buffer'), buffer) + t.assert.deepStrictEqual(fromBigInt(big, { length, format: 'uint8' }), uint8) + t.assert.deepStrictEqual(fromBigInt(big, { length, format: 'arraybuffer' }), ab) + t.assert.deepStrictEqual(fromBigInt(big, { length, format: 'buffer' }), buffer) if (uint8[0] > 0) { t.assert.throws(() => fromBigInt(big, { length: length - 1 })) } else if (length > 1) { diff --git a/tests/hex.test.js b/tests/hex.test.js index 5c67d69..94caa3b 100644 --- a/tests/hex.test.js +++ b/tests/hex.test.js @@ -15,7 +15,9 @@ const pool = raw.map((uint8) => { const buffer = Buffer.from(uint8) const shared = new Uint8Array(new SharedArrayBuffer(uint8.length)) shared.set(uint8) - return { uint8, shared, buffer, hex: buffer.toString('hex') } + const ab = uint8.buffer + if (ab.byteLength !== uint8.byteLength) throw new Error('Unexpected pooled Uint8Array') + return { uint8, ab, shared, buffer, hex: buffer.toString('hex') } }) const INVALID = [ @@ -105,7 +107,7 @@ describe('fromHex', () => { t.assert.throws(() => fromHex(input)) t.assert.throws(() => lib.fromHex(input)) t.assert.throws(() => js.fromHex(input)) - for (const form of ['uint8', 'buffer', 'hex']) { + for (const form of ['uint8', 'arraybuffer', 'buffer', 'hex']) { t.assert.throws(() => fromHex(input, form)) t.assert.throws(() => lib.fromHex(input, form)) } @@ -148,6 +150,21 @@ describe('fromHex', () => { } }) + test('arraybuffer, fixtures', (t) => { + for (const [hex, uint8] of VALID) { + t.assert.deepStrictEqual(uint8.byteLength, uint8.buffer.byteLength, 'coherence') + t.assert.deepStrictEqual(fromHex(hex, 'arraybuffer'), uint8.buffer) + t.assert.deepStrictEqual(lib.fromHex(hex, 'arraybuffer'), uint8.buffer) + } + }) + + test('arraybuffer, random', (t) => { + for (const { hex, ab } of pool) { + t.assert.deepStrictEqual(fromHex(hex, 'arraybuffer'), ab) + t.assert.deepStrictEqual(lib.fromHex(hex, 'arraybuffer'), ab) + } + }) + test('fromHex returns non-pooled Uint8Array instances', (t) => { for (let i = 0; i < 256; i++) { t.assert.strictEqual(fromHex('aa'.repeat(128)).buffer.byteLength, 128) diff --git a/tests/utf8.lib.test.js b/tests/utf8.lib.test.js index c226a8b..5cece8e 100644 --- a/tests/utf8.lib.test.js +++ b/tests/utf8.lib.test.js @@ -151,7 +151,7 @@ describe('utf8fromString', () => { test(method.name, (t) => { for (const input of [...[null, undefined, [], [1, 2], ['00'], new Uint8Array()]]) { t.assert.throws(() => method(input)) - for (const form of ['uint8', 'buffer', 'hex']) { + for (const form of ['uint8', 'arraybuffer', 'buffer', 'hex']) { t.assert.throws(() => method(input, form)) } } @@ -172,6 +172,16 @@ describe('utf8fromString', () => { } }) } + + for (const format of ['uint8', 'buffer', 'arraybuffer']) { + test(`format: ${format}`, (t) => { + for (const { charcodes, hex } of fixtures) { + const str = String.fromCharCode(...charcodes) + t.assert.deepStrictEqual(utf8fromString(str, format), fromHex(hex, format)) + t.assert.deepStrictEqual(utf8fromStringLoose(str, format), fromHex(hex, format)) + } + }) + } }) test('orphans throw in utf8fromString', (t) => { diff --git a/tests/utf8.test.js b/tests/utf8.test.js index 3e831a7..00909a2 100644 --- a/tests/utf8.test.js +++ b/tests/utf8.test.js @@ -155,7 +155,7 @@ describe('utf8fromString', () => { test(method.name, (t) => { for (const input of [...[null, undefined, [], [1, 2], ['00'], new Uint8Array()]]) { t.assert.throws(() => method(input)) - for (const form of ['uint8', 'buffer', 'hex']) { + for (const form of ['uint8', 'arraybuffer', 'buffer', 'hex']) { t.assert.throws(() => method(input, form)) } } @@ -176,6 +176,16 @@ describe('utf8fromString', () => { } }) } + + for (const format of ['uint8', 'buffer', 'arraybuffer']) { + test(`format: ${format}`, (t) => { + for (const { charcodes, hex } of fixtures) { + const str = String.fromCharCode(...charcodes) + t.assert.deepStrictEqual(utf8fromString(str, format), fromHex(hex, format)) + t.assert.deepStrictEqual(utf8fromStringLoose(str, format), fromHex(hex, format)) + } + }) + } }) test('orphans throw in utf8fromString', (t) => { diff --git a/utf8.d.ts b/utf8.d.ts index 9ac1333..091115a 100644 --- a/utf8.d.ts +++ b/utf8.d.ts @@ -35,8 +35,9 @@ import type { OutputFormat, Uint8ArrayBuffer } from './array.js'; * @returns The encoded bytes */ export function utf8fromString(string: string, format?: 'uint8'): Uint8ArrayBuffer; +export function utf8fromString(string: string, format: 'arraybuffer'): ArrayBuffer; export function utf8fromString(string: string, format: 'buffer'): Buffer; -export function utf8fromString(string: string, format?: OutputFormat): Uint8ArrayBuffer | Buffer; +export function utf8fromString(string: string, format?: OutputFormat): Uint8ArrayBuffer | ArrayBuffer | Buffer; /** * Encode a string to UTF-8 bytes (loose mode) @@ -59,11 +60,12 @@ export function utf8fromString(string: string, format?: OutputFormat): Uint8Arra * @returns The encoded bytes */ export function utf8fromStringLoose(string: string, format?: 'uint8'): Uint8ArrayBuffer; +export function utf8fromStringLoose(string: string, format: 'arraybuffer'): ArrayBuffer; export function utf8fromStringLoose(string: string, format: 'buffer'): Buffer; export function utf8fromStringLoose( string: string, format?: OutputFormat -): Uint8ArrayBuffer | Buffer; +): Uint8ArrayBuffer | ArrayBuffer | Buffer; /** * Decode UTF-8 bytes to a string (strict mode)