From 8c999badddd43cd643eaa58f359d1a0ae821422c Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 4 Aug 2020 17:23:00 +0100 Subject: [PATCH] fix: replace node buffers with uint8arrays (#70) This module now accepts Uint8Arrays as well as node Buffers and returns Uint8Arrays. Internally it converts non-Buffers into Buffers because the ethereum libs require that. BREAKING CHANGES: - `util.serialize` returns a `Uint8Array` - `util.cid` returns `CID`s with a breaking API change - see https://github.com/multiformats/js-cid/pull/117 for changes --- package.json | 14 ++++++-------- src/resolver.js | 7 +++---- src/util.js | 13 +++++++++---- test/mod.spec.js | 5 +---- test/parse.spec.js | 5 +---- test/resolver.spec.js | 5 +---- test/util.spec.js | 26 ++++++++++++++++++++------ 7 files changed, 41 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 67139e2..7d00f63 100644 --- a/package.json +++ b/package.json @@ -37,17 +37,15 @@ "homepage": "https://github.com/ipld/js-ipld-git", "dependencies": { "buffer": "^5.6.0", - "cids": "^0.8.3", - "multicodec": "^1.0.2", - "multihashing-async": "^1.0.0", + "cids": "^1.0.0", + "multicodec": "^2.0.0", + "multihashing-async": "^2.0.0", "smart-buffer": "^4.1.0", - "strftime": "^0.10.0" + "strftime": "^0.10.0", + "uint8arrays": "^1.0.0" }, "devDependencies": { - "aegir": "^25.0.0", - "chai": "^4.2.0", - "chai-as-promised": "^7.1.1", - "dirty-chai": "^2.0.1" + "aegir": "^25.0.0" }, "contributors": [ "Volker Mische ", diff --git a/src/resolver.js b/src/resolver.js index 5f6e0c2..9cb736e 100644 --- a/src/resolver.js +++ b/src/resolver.js @@ -1,7 +1,6 @@ 'use strict' const CID = require('cids') -const { Buffer } = require('buffer') const util = require('./util') @@ -11,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 Git block + * @param {Uint8Array} binaryBlob - Binary representation of a Git 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 @@ -46,7 +45,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 } @@ -61,7 +60,7 @@ const traverse = function * (node, path) { * Return all available paths of a block. * * @generator - * @param {Buffer} binaryBlob - Binary representation of a Bitcoin block + * @param {Uint8Array} binaryBlob - Binary representation of a Bitcoin block * @yields {string} - A single path */ exports.tree = function * (binaryBlob) { diff --git a/src/util.js b/src/util.js index 98c0a40..de9efb4 100644 --- a/src/util.js +++ b/src/util.js @@ -4,6 +4,7 @@ const multihashing = require('multihashing-async') const CID = require('cids') const multicodec = require('multicodec') const { Buffer } = require('buffer') +const uint8ArrayToString = require('uint8arrays/to-string') const gitUtil = require('./util/util') @@ -20,15 +21,15 @@ exports.defaultHashAlg = multicodec.SHA1 * Serialize internal representation into a binary Git block. * * @param {GitBlock} dagNode - Internal representation of a Git block - * @returns {Buffer} + * @returns {Uint8Array} */ exports.serialize = (dagNode) => { if (dagNode === null) { throw new Error('dagNode passed to serialize was null') } - if (Buffer.isBuffer(dagNode)) { - if (dagNode.slice(0, 4).toString() === 'blob') { + if (dagNode instanceof Uint8Array) { + if (uint8ArrayToString(dagNode.slice(0, 4)) === 'blob') { return dagNode } else { throw new Error('unexpected dagNode passed to serialize') @@ -49,10 +50,14 @@ exports.serialize = (dagNode) => { /** * Deserialize Git block into the internal representation. * - * @param {Buffer} data - Binary representation of a Git block. + * @param {Uint8Array} data - Binary representation of a Git block. * @returns {BitcoinBlock} */ exports.deserialize = (data) => { + if (!Buffer.isBuffer(data)) { + data = Buffer.from(data, data.byteOffset, data.byteLength) + } + const headLen = gitUtil.find(data, 0) const head = data.slice(0, headLen).toString() const typeLen = head.match(/([^ ]+) (\d+)/) diff --git a/test/mod.spec.js b/test/mod.spec.js index 9f49c47..9ec41e5 100644 --- a/test/mod.spec.js +++ b/test/mod.spec.js @@ -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 multicodec = require('multicodec') const mod = require('../src') diff --git a/test/parse.spec.js b/test/parse.spec.js index b6f7ab4..bc5681a 100644 --- a/test/parse.spec.js +++ b/test/parse.spec.js @@ -3,10 +3,7 @@ '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 { Buffer } = require('buffer') const loadFixture = require('aegir/fixtures') const zlib = require('zlib') diff --git a/test/resolver.spec.js b/test/resolver.spec.js index 2b32945..0149b02 100644 --- a/test/resolver.spec.js +++ b/test/resolver.spec.js @@ -2,10 +2,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 { Buffer } = require('buffer') const CID = require('cids') diff --git a/test/util.spec.js b/test/util.spec.js index 5c38ab1..1b0672e 100644 --- a/test/util.spec.js +++ b/test/util.spec.js @@ -1,17 +1,13 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const chaiAsProised = require('chai-as-promised') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(chaiAsProised) -chai.use(dirtyChai) +const { expect } = require('aegir/utils/chai') const ipldGit = require('../src') const multicodec = require('multicodec') const multihash = require('multihashing-async').multihash const CID = require('cids') const { Buffer } = require('buffer') +const uint8ArrayFromString = require('uint8arrays/from-string') describe('IPLD format util', () => { const tagNode = { @@ -28,6 +24,13 @@ describe('IPLD format util', () => { } const tagBlob = ipldGit.util.serialize(tagNode) + it('.serialize from Uint8Array', () => { + const node = uint8ArrayFromString('blob-blob') + const blob = ipldGit.util.serialize(node) + + expect(blob).to.deep.equal(node) + }) + it('.serialize and .deserialize', () => { expect(Buffer.isBuffer(tagBlob)).to.be.true() const deserialized = ipldGit.util.deserialize(tagBlob) @@ -39,6 +42,17 @@ describe('IPLD format util', () => { expect(deserialized).to.eql(expected) }) + it('.serialize and .deserialize Uint8Array', () => { + expect(Buffer.isBuffer(Uint8Array.of(...tagBlob))).to.be.false() + const deserialized = ipldGit.util.deserialize(Uint8Array.of(...tagBlob)) + + // The `gitType` is not enumerable, hence `eql()` would find it. Thus + // remove that property so that that check passes + const expected = Object.assign({}, tagNode) + delete expected.gitType + expect(deserialized).to.eql(expected) + }) + it('.cid', async () => { const cid = await ipldGit.util.cid(tagBlob) expect(cid.version).to.equal(1)