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

fix: replace node Buffers with Uint8Arrays #187

Merged
merged 5 commits into from
Aug 4, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ dagPB.util
#### Create a DAGNode

```JavaScript
const node1 = new DAGNode(Buffer.from('some data'))
const node1 = new DAGNode(new TextEncoder('utf8').encode('some data'))

// node2 will have the same data as node1
const node2 = new DAGNode('some data')
Expand Down Expand Up @@ -114,7 +114,7 @@ const DAGNode = dagPB.DAGNode

#### DAGNode constructor

- `data` - type: Buffer
- `data` - type: Uint8Array or String
- `links`- (optional) type: Array of DAGLink instances or Array of DAGLink instances in its json format (link.toJSON)
- `serializedSize`- (optional) type: Number of bytes the serialized node has. If none is given, it will automatically be calculated.

Expand Down Expand Up @@ -198,7 +198,7 @@ node.rmLink('Link1')

#### `node.serialize()`

Serialize the DAGNode instance to its portable binary format. Yields the same result as `dagPB.util.serialize(node)`. Returns a `Buffer`.
Serialize the DAGNode instance to its portable binary format. Yields the same result as `dagPB.util.serialize(node)`. Returns a `Uint8Array`.

### DAGLink functions

Expand Down Expand Up @@ -238,7 +238,6 @@ const link = new DAGLink(

> See: https://github.com/ipld/interface-ipld-format#local-resolver-methods


#### `dagPB.resolver.resolve`

#### `dagPB.resolver.tree`
Expand All @@ -251,7 +250,7 @@ const link = new DAGLink(

### `dagPB.util.serialize`

Serialize the DAGNode instance to its portable binary format. Yields the same result as `node.serialize()`. Returns a `Buffer`.
Serialize the DAGNode instance to its portable binary format. Yields the same result as `node.serialize()`. Returns a `Uint8Array`.

### `dagPB.util.deserialize`

Expand Down
25 changes: 14 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,25 @@
"npm": ">=3.0.0"
},
"dependencies": {
"buffer": "^5.6.0",
"cids": "~0.8.3",
"cids": "multiformats/js-cid#fix/support-uint8arrays",
"class-is": "^1.1.0",
"multicodec": "^1.0.3",
"multihashing-async": "^1.0.0",
"multicodec": "^2.0.0",
"multihashing-async": "^2.0.0",
"npm": "^6.14.7",
"protons": "^1.2.1",
"stable": "^0.1.8"
"reset": "^0.1.0",
"run": "^1.4.0",
"stable": "^0.1.8",
"uint8arrays": "^1.0.0"
},
"devDependencies": {
"aegir": "^23.0.0",
"aegir": "^25.0.0",
"fs-extra": "^9.0.1",
"ipfs-block-service": "~0.17.1",
"ipfs-repo": "^4.0.0",
"ipfs-block-service": "^0.17.1",
"ipfs-repo": "^5.0.0",
"ipfs-utils": "^2.3.1",
"ipld-block": "~0.9.2",
"multibase": "^1.0.1",
"multihashes": "^1.0.1"
"ipld-block": "^0.9.2",
"multibase": "^3.0.0",
"multihashes": "^3.0.0"
}
}
8 changes: 4 additions & 4 deletions src/dag-link/dagLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const CID = require('cids')
const withIs = require('class-is')
const { Buffer } = require('buffer')
const uint8ArrayFromString = require('uint8arrays/from-string')

// Link represents an IPFS Merkle DAG Link between Nodes.
class DAGLink {
Expand Down Expand Up @@ -39,15 +39,15 @@ class DAGLink {
return Object.assign({}, this._json)
}

// Memoize the Buffer representation of name
// Memoize the Uint8Array representation of name
// We need this to sort the links, otherwise
// we will reallocate new buffers every time
// we will reallocate new Uint8Arrays every time
get nameAsBuffer () {
if (this._nameBuf !== null) {
return this._nameBuf
}

this._nameBuf = Buffer.from(this.Name)
this._nameBuf = uint8ArrayFromString(this.Name)
return this._nameBuf
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/dag-node/dagNode.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
'use strict'

const withIs = require('class-is')
const { Buffer } = require('buffer')
const sortLinks = require('./sortLinks')
const DAGLink = require('../dag-link/dagLink')
const { serializeDAGNode } = require('../serialize.js')
const toDAGLink = require('./toDagLink')
const addLink = require('./addLink')
const rmLink = require('./rmLink')
const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayToString = require('uint8arrays/to-string')

class DAGNode {
constructor (data, links = [], serializedSize = null) {
if (!data) {
data = Buffer.alloc(0)
data = new Uint8Array(0)
}
if (typeof data === 'string') {
data = Buffer.from(data)
data = uint8ArrayFromString(data)
}
if (!Buffer.isBuffer(data)) {
throw new Error('Passed \'data\' is not a buffer or a string!')

if (!(data instanceof Uint8Array)) {
throw new Error('Passed \'data\' is not a Uint8Array or a String!')
}

if (serializedSize !== null && typeof serializedSize !== 'number') {
Expand Down Expand Up @@ -53,7 +55,7 @@ class DAGNode {
}

toString () {
return `DAGNode <data: "${this.Data.toString('base64')}", links: ${this.Links.length}, size: ${this.size}>`
return `DAGNode <data: "${uint8ArrayToString(this.Data, 'base64urlpad')}", links: ${this.Links.length}, size: ${this.size}>`
}

_invalidateCached () {
Expand Down
6 changes: 3 additions & 3 deletions src/dag-node/rmLink.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
'use strict'

const CID = require('cids')
const { Buffer } = require('buffer')
const uint8ArrayEquals = require('uint8arrays/equals')

const rmLink = (dagNode, nameOrCid) => {
let predicate = null

// It's a name
if (typeof nameOrCid === 'string') {
predicate = (link) => link.Name === nameOrCid
} else if (Buffer.isBuffer(nameOrCid) || CID.isCID(nameOrCid)) {
predicate = (link) => link.Hash.equals(nameOrCid)
} else if (nameOrCid instanceof Uint8Array || CID.isCID(nameOrCid)) {
predicate = (link) => uint8ArrayEquals(link.Hash, nameOrCid)
}

if (predicate) {
Expand Down
7 changes: 5 additions & 2 deletions src/dag-node/sortLinks.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
'use strict'

const { Buffer } = require('buffer')
const sort = require('stable')
const uint8ArrayCompare = require('uint8arrays/compare')

const linkSort = (a, b) => {
return Buffer.compare(a.nameAsBuffer, b.nameAsBuffer)
const buf1 = a.nameAsBuffer
const buf2 = b.nameAsBuffer

return uint8ArrayCompare(buf1, buf2)
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,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 PB block
* @param {Uint8Array} binaryBlob - Binary representation of a PB 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 @@ -58,7 +58,7 @@ exports.resolve = (binaryBlob, path) => {
* Return all available paths of a block.
*
* @generator
* @param {Buffer} binaryBlob - Binary representation of a PB block
* @param {Uint8Array} binaryBlob - Binary representation of a PB block
* @yields {string} - A single path
*/
exports.tree = function * (binaryBlob) {
Expand Down
6 changes: 3 additions & 3 deletions src/serialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ const toProtoBuf = (node) => {
pbn.Data = node.Data
} else {
// NOTE: this has to be null in order to match go-ipfs serialization
// `null !== new Buffer(0)`
// `null !== new Uint8Array(0)`
pbn.Data = null
}

if (node.Links && node.Links.length > 0) {
pbn.Links = node.Links
.map((link) => ({
Hash: link.Hash.buffer,
Hash: link.Hash.bytes,
Name: link.Name,
Tsize: link.Tsize
}))
Expand All @@ -35,7 +35,7 @@ const toProtoBuf = (node) => {
* Serialize internal representation into a binary PB block.
*
* @param {Object} node - Internal representation of a PB block
* @returns {Buffer} - The encoded binary representation
* @returns {Uint8Array} - The encoded binary representation
*/
const serializeDAGNode = (node) => {
const data = node.Data
Expand Down
9 changes: 4 additions & 5 deletions src/util.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use strict'

const { Buffer } = require('buffer')
const protons = require('protons')
const proto = protons(require('./dag.proto'))
const DAGLink = require('./dag-link/dagLink')
Expand Down Expand Up @@ -30,7 +29,7 @@ const cid = (binaryBlob, userOptions) => {
* Serialize internal representation into a binary PB block.
*
* @param {Object} node - Internal representation of a CBOR block
* @returns {Buffer} - The encoded binary representation
* @returns {Uint8Array} - The encoded binary representation
*/
const serialize = (node) => {
if (DAGNode.isDAGNode(node)) {
Expand All @@ -43,7 +42,7 @@ const serialize = (node) => {
/**
* Deserialize PB block into the internal representation.
*
* @param {Buffer} buffer - Binary representation of a PB block
* @param {Uint8Array} buffer - Binary representation of a PB block
* @returns {Object} - An object that conforms to the IPLD Data Model
*/
const deserialize = (buffer) => {
Expand All @@ -53,9 +52,9 @@ const deserialize = (buffer) => {
return new DAGLink(link.Name, link.Tsize, link.Hash)
})

const data = pbn.Data == null ? Buffer.alloc(0) : pbn.Data
const data = pbn.Data == null ? new Uint8Array(0) : pbn.Data

return new DAGNode(data, links, buffer.length)
return new DAGNode(data, links, buffer.byteLength)
}

exports.serialize = serialize
Expand Down
7 changes: 4 additions & 3 deletions test/dag-link-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
'use strict'

const chai = require('aegir/utils/chai')
const { Buffer } = require('buffer')
const expect = chai.expect
const CID = require('cids')
const DAGLink = require('../src').DAGLink
const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayToString = require('uint8arrays/to-string')

module.exports = (repo) => {
describe('DAGLink', () => {
describe('create with multihash as b58 encoded string', () => {
it('string', () => {
const link = new DAGLink('hello', 3, 'QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39U')

expect(link.Hash.buffer.toString('hex'))
expect(uint8ArrayToString(link.Hash.bytes, 'base16'))
.to.equal('12208ab7a6c5e74737878ac73863cb76739d15d4666de44e5756bf55a2f9e9ab5f43')
})

Expand All @@ -23,7 +24,7 @@ module.exports = (repo) => {
})

it('create with multihash as a multihash Buffer', () => {
const link = new DAGLink('hello', 3, Buffer.from('12208ab7a6c5e74737878ac73863cb76739d15d4666de44e5756bf55a2f9e9ab5f43', 'hex'))
const link = new DAGLink('hello', 3, uint8ArrayFromString('12208ab7a6c5e74737878ac73863cb76739d15d4666de44e5756bf55a2f9e9ab5f43', 'base16'))

expect(new CID(link.Hash).toBaseEncodedString())
.to.equal('QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39U')
Expand Down
Loading