Skip to content

Commit e7f3272

Browse files
authored
feat: support decoding ArrayBuffers (#287)
When using `fetch` to download something over HTTP, it only makes an `ArrayBuffer` available, not a `Uint8Array`. `TextDecoder` supports decoding `ArrayBuffer`s, and the `raw` codec turns passed `ArrayBuffer`s into `Uint8Array`s so this is just a type change. Instead of: ```js const res = await fetch('...') const obj = json.decode(new Uint8Array(await res.arrayBuffer())) ``` we can do: ```js const res = await fetch('...') const obj = json.decode(await res.arrayBuffer()) ```
1 parent aa9c730 commit e7f3272

File tree

5 files changed

+24
-7
lines changed

5 files changed

+24
-7
lines changed

src/block/interface.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ import type { Link, Version } from '../link/interface.js'
1212
*/
1313
export interface ByteView<Data> extends Uint8Array, Phantom<Data> {}
1414

15+
/**
16+
* Similar to ByteView but extends ArrayBuffer.
17+
*/
18+
export interface ArrayBufferView<Data> extends ArrayBuffer, Phantom<Data> {}
19+
1520
declare const Marker: unique symbol
1621

1722
/**

src/codecs/interface.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ByteView } from '../block/interface.js'
1+
import type { ArrayBufferView, ByteView } from '../block/interface.js'
22

33
/**
44
* IPLD encoder part of the codec.
@@ -14,12 +14,12 @@ export interface BlockEncoder<Code extends number, T> {
1414
*/
1515
export interface BlockDecoder<Code extends number, T> {
1616
code: Code
17-
decode(bytes: ByteView<T>): T
17+
decode(bytes: ByteView<T> | ArrayBufferView<T>): T
1818
}
1919

2020
/**
2121
* An IPLD codec is a combination of both encoder and decoder.
2222
*/
2323
export interface BlockCodec<Code extends number, T> extends BlockEncoder<Code, T>, BlockDecoder<Code, T> {}
2424

25-
export type { ByteView }
25+
export type { ArrayBufferView, ByteView }

src/codecs/json.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ByteView } from './interface.js'
1+
import type { ArrayBufferView, ByteView } from './interface.js'
22

33
const textEncoder = new TextEncoder()
44
const textDecoder = new TextDecoder()
@@ -10,6 +10,6 @@ export function encode <T> (node: T): ByteView<T> {
1010
return textEncoder.encode(JSON.stringify(node))
1111
}
1212

13-
export function decode <T> (data: ByteView<T>): T {
13+
export function decode <T> (data: ByteView<T> | ArrayBufferView<T>): T {
1414
return JSON.parse(textDecoder.decode(data))
1515
}

src/codecs/raw.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { coerce } from '../bytes.js'
2-
import type { ByteView } from './interface.js'
2+
import type { ArrayBufferView, ByteView } from './interface.js'
33

44
export const name = 'raw'
55
export const code = 0x55
@@ -8,6 +8,6 @@ export function encode (node: Uint8Array): ByteView<Uint8Array> {
88
return coerce(node)
99
}
1010

11-
export function decode (data: ByteView<Uint8Array>): Uint8Array {
11+
export function decode (data: ByteView<Uint8Array> | ArrayBufferView<Uint8Array>): Uint8Array {
1212
return coerce(data)
1313
}

test/test-multicodec.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,24 @@ describe('multicodec', () => {
1212
assert.deepStrictEqual(raw.decode(buff), bytes.fromString('test'))
1313
})
1414

15+
it('encode/decode raw arraybuffer', () => {
16+
const buff = raw.encode(bytes.fromString('test'))
17+
assert.deepStrictEqual(buff, bytes.fromString('test'))
18+
assert.deepStrictEqual(raw.decode(buff.buffer), bytes.fromString('test'))
19+
})
20+
1521
it('encode/decode json', () => {
1622
const buff = json.encode({ hello: 'world' })
1723
assert.deepStrictEqual(buff, bytes.fromString(JSON.stringify({ hello: 'world' })))
1824
assert.deepStrictEqual(json.decode(buff), { hello: 'world' })
1925
})
2026

27+
it('encode/decode json arraybuffer', () => {
28+
const buff = json.encode({ hello: 'world' })
29+
assert.deepStrictEqual(buff, bytes.fromString(JSON.stringify({ hello: 'world' })))
30+
assert.deepStrictEqual(json.decode(buff.buffer), { hello: 'world' })
31+
})
32+
2133
it('raw cannot encode string', async () => {
2234
// @ts-expect-error - 'string' is not assignable to parameter of type 'Uint8Array'
2335
assert.throws(() => raw.encode('asdf'), 'Unknown type, must be binary type')

0 commit comments

Comments
 (0)