Skip to content

Commit

Permalink
feat: support decoding ArrayBuffers (#95)
Browse files Browse the repository at this point in the history
Expands supported input types to include `ArrayBuffer`s to make it
easiser for users to use modules like `fetch` that don't return
`Uint8Array`s.
  • Loading branch information
achingbrain authored Feb 16, 2024
1 parent 606cdcd commit 3d4eaf8
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 4 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@
"dep-check": "aegir dep-check -i @ipld/dag-pb"
},
"dependencies": {
"multiformats": "^13.0.0"
"multiformats": "^13.1.0"
},
"devDependencies": {
"aegir": "^42.1.0"
Expand Down
12 changes: 9 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { CID } from 'multiformats/cid'
import { decodeNode } from './pb-decode.js'
import { encodeNode } from './pb-encode.js'
import { prepare, validate, createNode, createLink } from './util.js'
import { prepare, validate, createNode, createLink, toByteView } from './util.js'

/**
* @template T
* @typedef {import('multiformats/codecs/interface').ByteView<T>} ByteView
*/

/**
* @template T
* @typedef {import('multiformats/codecs/interface').ArrayBufferView<T>} ArrayBufferView
*/

/**
* @typedef {import('./interface.js').PBLink} PBLink
* @typedef {import('./interface.js').PBNode} PBNode
Expand Down Expand Up @@ -47,11 +52,12 @@ export function encode (node) {
}

/**
* @param {ByteView<PBNode>} bytes
* @param {ByteView<PBNode> | ArrayBufferView<PBNode>} bytes
* @returns {PBNode}
*/
export function decode (bytes) {
const pbn = decodeNode(bytes)
const buf = toByteView(bytes)
const pbn = decodeNode(buf)

const node = {}

Expand Down
23 changes: 23 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ import { CID } from 'multiformats/cid'
* @typedef {import('./interface.js').PBNode} PBNode
*/

/**
* @template T
* @typedef {import('multiformats/codecs/interface').ByteView<T>} ByteView
*/

/**
* @template T
* @typedef {import('multiformats/codecs/interface').ArrayBufferView<T>} ArrayBufferView
*/

const pbNodeProperties = ['Data', 'Links']
const pbLinkProperties = ['Hash', 'Name', 'Tsize']

Expand Down Expand Up @@ -231,3 +241,16 @@ export function createNode (data, links = []) {
export function createLink (name, size, cid) {
return asLink({ Hash: cid, Name: name, Tsize: size })
}

/**
* @template T
* @param {ByteView<T> | ArrayBufferView<T>} buf
* @returns {ByteView<T>}
*/
export function toByteView (buf) {
if (buf instanceof ArrayBuffer) {
return new Uint8Array(buf, 0, buf.byteLength)
}

return buf
}
11 changes: 11 additions & 0 deletions test/test-basics.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ describe('Basics', () => {
assert.deepEqual(node.Data, data)
})

it('prepare & encode a node with data using an ArrayBuffer', () => {
const data = Uint8Array.from([0, 1, 2, 3, 4])
const prepared = prepare({ Data: data })
assert.deepEqual(prepared, { Data: data, Links: [] })
const result = encode(prepared)
assert.instanceOf(result, Uint8Array)

const node = decode(result.buffer)
assert.deepEqual(node.Data, data)
})

it('prepare & encode a node with links', () => {
const links = [
{ Hash: CID.parse('QmWDtUQj38YLW8v3q4A6LwPn4vYKEbuKWpgSm6bjKW6Xfe') }
Expand Down
9 changes: 9 additions & 0 deletions test/ts-use/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ function useCodec (codec: BlockCodec<0x70, any>) {
// use only as a BlockDecoder
useDecoder(codec)

// use with ArrayBuffer input type
useDecoderWithArrayBuffer(codec)

// use as a full BlockCodec which does both BlockEncoder & BlockDecoder
useBlockCodec(codec)
}
Expand All @@ -36,6 +39,12 @@ function useDecoder<Codec extends number> (decoder: BlockDecoder<Codec, Uint8Arr
console.log('[TS] ✓ { decoder: BlockDecoder }')
}

function useDecoderWithArrayBuffer<Codec extends number> (decoder: BlockDecoder<Codec, Uint8Array>) {
deepStrictEqual(decoder.code, 0x70)
deepStrictEqual(decoder.decode(Uint8Array.from(exampleBytes).buffer), exampleNode)
console.log('[TS] ✓ { decoder: BlockDecoder }')
}

function useBlockCodec<Codec extends number> (blockCodec: BlockCodec<Codec, PBNode>) {
deepStrictEqual(blockCodec.code, 0x70)
deepStrictEqual(blockCodec.name, 'dag-pb')
Expand Down

0 comments on commit 3d4eaf8

Please sign in to comment.