Skip to content
This repository has been archived by the owner on Aug 11, 2021. It is now read-only.

Commit

Permalink
fix: replace node buffers with uint8arrays (#134)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

- `util.serialize` now returns a Uint8Array
  • Loading branch information
achingbrain authored Aug 4, 2020
1 parent 4646b62 commit 41587e7
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 50 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# js-ipld-dag-cbor
# js-ipld-dag-cbor <!-- omit in toc -->

[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-IPLD-blue.svg?style=flat-square)](http://github.com/ipld/ipld)
Expand All @@ -14,11 +14,11 @@

> JavaScript implementation of the [IPLD spec](https://github.com/ipfs/specs/tree/master/ipld).
## Lead Maintainer
## Lead Maintainer <!-- omit in toc -->

[Volker Mische](https://github.com/vmx)

## Table of Contents
## Table of Contents <!-- omit in toc -->

- [Install](#install)
- [npm](#npm)
Expand All @@ -27,6 +27,10 @@
- [Use in a browser Using a script tag](#use-in-a-browser-using-a-script-tag)
- [Usage](#usage)
- [API](#api)
- [`dagCBOR.util.serialize(obj)`](#dagcborutilserializeobj)
- [`dagCBOR.util.deserialize(serialized)`](#dagcborutildeserializeserialized)
- [`dagCBOR.util.configureDecoder([options])`](#dagcborutilconfiguredecoderoptions)
- [`dagCBOR.util.cid(obj[, options,])`](#dagcborutilcidobj-options)
- [Contribute](#contribute)
- [License](#license)

Expand Down Expand Up @@ -73,13 +77,13 @@ const file = {
}

const serialized = dagCBOR.util.serialize(file)
console.log(`Encoded as a ${serialized.length} byte Buffer`)
console.log(`Encoded as a ${serialized.length} byte Uint8Array`)

const node = dagCBOR.util.deserialize(serialized)
console.log('Decoded as:', node)
require('assert').deepEqual(node, file) // should match

// → Encoded as a 22 byte Buffer
// → Encoded as a 22 byte Uint8Array
// → Decoded as: { name: 'hello.txt', size: 11 }
```

Expand All @@ -97,7 +101,7 @@ Returns the serialized node.

Decodes an IPLD CBOR encoded representation, restoring any CBOR tags (id `42`) to CIDs.

- `serialized` (`Buffer` or `String`): a binary blob representing an IPLD CBOR encoded object.
- `serialized` (`Uint8Array` or `String`): a binary blob representing an IPLD CBOR encoded object.

Returns the deserialized object.

Expand Down
12 changes: 5 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,17 @@
"homepage": "https://github.com/ipld/js-ipld-dag-cbor",
"dependencies": {
"borc": "^2.1.2",
"buffer": "^5.6.0",
"cids": "~0.8.3",
"cids": "^1.0.0",
"is-circular": "^1.0.2",
"multicodec": "^1.0.3",
"multihashing-async": "^1.0.0"
"multicodec": "^2.0.0",
"multihashing-async": "^2.0.0",
"uint8arrays": "^1.0.0"
},
"devDependencies": {
"aegir": "^25.0.0",
"chai": "^4.2.0",
"detect-node": "^2.0.4",
"dirty-chai": "^2.0.1",
"garbage": "0.0.0",
"multihashes": "^1.0.1"
"multihashes": "^3.0.1"
},
"contributors": [
"David Dias <daviddias.p@gmail.com>",
Expand Down
7 changes: 3 additions & 4 deletions src/resolver.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict'

const CID = require('cids')
const { Buffer } = require('buffer')
const util = require('./util')

/**
Expand All @@ -10,7 +9,7 @@ const util = require('./util')
* Returns the value or a link and the partial mising path. This way the
* IPLD Resolver can fetch the link and continue to resolve.
*
* @param {Buffer} binaryBlob - Binary representation of a CBOR block
* @param {Uint8Array} binaryBlob - Binary representation of a CBOR block
* @param {string} [path='/'] - Path that should be resolved
* @returns {Object} result - Result of the path it it was resolved successfully
* @returns {*} result.value - Value the path resolves to
Expand Down Expand Up @@ -45,7 +44,7 @@ exports.resolve = (binaryBlob, path) => {

const traverse = function * (node, path) {
// Traverse only objects and arrays
if (Buffer.isBuffer(node) || CID.isCID(node) || typeof node === 'string' ||
if (node instanceof Uint8Array || CID.isCID(node) || typeof node === 'string' ||
node === null) {
return
}
Expand All @@ -60,7 +59,7 @@ const traverse = function * (node, path) {
* Return all available paths of a block.
*
* @generator
* @param {Buffer} binaryBlob - Binary representation of a CBOR block
* @param {Uint8Array} binaryBlob - Binary representation of a CBOR block
* @yields {string} - A single path
*/
exports.tree = function * (binaryBlob) {
Expand Down
17 changes: 9 additions & 8 deletions src/util.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
'use strict'

const cbor = require('borc')
const { Buffer } = require('buffer')
const multicodec = require('multicodec')
const multihashing = require('multihashing-async')
const CID = require('cids')
const isCircular = require('is-circular')
const uint8ArrayConcat = require('uint8arrays/concat')
const uint8ArrayFromString = require('uint8arrays/from-string')

// https://github.com/ipfs/go-ipfs/issues/3570#issuecomment-273931692
const CID_CBOR_TAG = 42

function tagCID (cid) {
if (typeof cid === 'string') {
cid = new CID(cid).buffer
cid = new CID(cid).bytes
} else if (CID.isCID(cid)) {
cid = cid.buffer
cid = cid.bytes
}

return new cbor.Tagged(CID_CBOR_TAG, Buffer.concat([
Buffer.from('00', 'hex'), // thanks jdag
return new cbor.Tagged(CID_CBOR_TAG, uint8ArrayConcat([
uint8ArrayFromString('00', 'base16'), // thanks jdag
cid
]))
], 1 + cid.length))
}

function replaceCIDbyTAG (dagNode) {
Expand Down Expand Up @@ -129,7 +130,7 @@ exports.configureDecoder() // Setup default cbor.Decoder
* Serialize internal representation into a binary CBOR block.
*
* @param {Object} node - Internal representation of a CBOR block
* @returns {Buffer} - The encoded binary representation
* @returns {Uint8Array} - The encoded binary representation
*/
exports.serialize = (node) => {
const nodeTagged = replaceCIDbyTAG(node)
Expand All @@ -141,7 +142,7 @@ exports.serialize = (node) => {
/**
* Deserialize CBOR block into the internal representation.
*
* @param {Buffer} data - Binary representation of a CBOR block
* @param {Uint8Array} data - Binary representation of a CBOR block
* @returns {Object} - An object that conforms to the IPLD Data Model
*/
exports.deserialize = (data) => {
Expand Down
5 changes: 1 addition & 4 deletions test/interop.spec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
/* eslint-env mocha */
'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const { expect } = require('aegir/utils/chai')
const dagCBOR = require('../src')
const loadFixture = require('aegir/fixtures')
const isNode = require('detect-node')
Expand Down
6 changes: 1 addition & 5 deletions test/mod.spec.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
/* eslint-env mocha */
'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const { expect } = require('aegir/utils/chai')
const multicodec = require('multicodec')

const mod = require('../src')

describe('IPLD Format', () => {
Expand Down
7 changes: 1 addition & 6 deletions test/resolver.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@
/* eslint max-nested-callbacks: ["error", 5] */
'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)

const { expect } = require('aegir/utils/chai')
const CID = require('cids')

const dagCBOR = require('../src')
const resolver = dagCBOR.resolver

Expand Down
18 changes: 8 additions & 10 deletions test/util.spec.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
/* eslint-env mocha */
'use strict'

const { Buffer } = require('buffer')
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const { expect } = require('aegir/utils/chai')
const garbage = require('garbage')
const dagCBOR = require('../src')
const multihash = require('multihashes')
const CID = require('cids')
const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayConcat = require('uint8arrays/concat')

describe('util', () => {
const obj = {
Expand All @@ -27,7 +25,7 @@ describe('util', () => {
const serializedObj = dagCBOR.util.serialize(obj)

it('.serialize and .deserialize', () => {
expect(Buffer.isBuffer(serializedObj)).to.equal(true)
expect(serializedObj).to.be.a('Uint8Array')

// Check for the tag 42
// d8 = tag, 2a = 42
Expand All @@ -45,7 +43,7 @@ describe('util', () => {
const largeObj = { someKey: [].slice.call(new Uint8Array(dataSize)) }

const serialized = dagCBOR.util.serialize(largeObj)
expect(Buffer.isBuffer(serialized)).to.be.true()
expect(serialized).to.be.a('Uint8Array')

const deserialized = dagCBOR.util.deserialize(serialized)
expect(largeObj).to.eql(deserialized)
Expand All @@ -60,7 +58,7 @@ describe('util', () => {

dagCBOR.util.configureDecoder({ size: 64 * 1024, maxSize: 128 * 1024 }) // 64 Kb start, 128 Kb max
const serialized = dagCBOR.util.serialize(largeObj)
expect(Buffer.isBuffer(serialized)).to.be.true()
expect(serialized).to.be.a('Uint8Array')

expect(() => dagCBOR.util.deserialize(serialized)).to.throw(
'Data is too large to deserialize with current decoder')
Expand Down Expand Up @@ -111,7 +109,7 @@ describe('util', () => {
})

it('.serialize and .deserialize object with Uint8Array field', () => {
const buffer = Buffer.from('some data')
const buffer = uint8ArrayFromString('some data')
const bytes = Uint8Array.from(buffer)

const s1 = dagCBOR.util.serialize({ data: buffer })
Expand All @@ -127,7 +125,7 @@ describe('util', () => {
expect(() =>
// two top-level CBOR objects, the original and a single uint=0, valid if using
// CBOR in streaming mode, not valid here
dagCBOR.util.deserialize(Buffer.concat([serializedObj, Buffer.alloc(1)]))
dagCBOR.util.deserialize(uint8ArrayConcat([serializedObj, new Uint8Array(1)]))
).to.throw(Error, 'Extraneous CBOR data found beyond initial top-level object')
})
})

0 comments on commit 41587e7

Please sign in to comment.