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

Commit

Permalink
feat: use async interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire authored and daviddias committed Oct 26, 2016
1 parent f76db73 commit 48eb863
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 87 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"babel-runtime": "^6.6.1",
"bs58": "^3.0.0",
"cbor": "^2.0.1",
"cbor-sync": "^1.0.2",
"cids": "^0.2.0",
"multihashes": "^0.2.2",
"multihashing": "^0.2.1",
Expand Down
98 changes: 61 additions & 37 deletions src/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,66 +11,90 @@ exports.multicodec = 'dag-cbor'
* resolve: receives a path and a block and returns the value on path,
* throw if not possible. `block` is an IPFS Block instance (contains data + key)
*/
exports.resolve = (block, path) => {
let node = util.deserialize(block.data)
exports.resolve = (block, path, callback) => {
if (typeof path === 'function') {
callback = path
path = undefined
}

// root
util.deserialize(block.data, (err, node) => {
if (err) {
return callback(err)
}

if (!path || path === '/') {
return { value: node, remainderPath: '' }
}
// root

// within scope
if (!path || path === '/') {
return callback(null, {
value: node,
remainderPath: ''
})
}

// const tree = exports.tree(block)
const parts = path.split('/')
const val = traverse(node).get(parts)
// within scope

if (val) {
return { value: val, remainderPath: '' }
}
console.log(val)
// const tree = exports.tree(block)
const parts = path.split('/')
const val = traverse(node).get(parts)

if (val) {
return callback(null, {
value: val,
remainderPath: ''
})
}

// out of scope
// out of scope

// TODO this was my first try at writting this out of scope traversal code,
// it REALLY needs way more testing.
let value
// TODO this was my first try at writting this out of scope traversal code,
// it REALLY needs way more testing.
let value

for (let i = 0; i < parts.length; i++) {
let partialPath = parts.shift()
for (let i = 0; i < parts.length; i++) {
let partialPath = parts.shift()

if (Array.isArray(node) && !Buffer.isBuffer(node)) {
value = node[Number(partialPath)]
} if (node[partialPath]) {
value = node[partialPath]
} else {
// can't traverse more
if (!value) {
throw new Error('path not available at root')
if (Array.isArray(node) && !Buffer.isBuffer(node)) {
value = node[Number(partialPath)]
} if (node[partialPath]) {
value = node[partialPath]
} else {
parts.unshift(partialPath)
return {
value: value,
remainderPath: parts.join('/')
// can't traverse more
if (!value) {
return callback(new Error('path not available at root'))
} else {
parts.unshift(partialPath)
return callback(null, {
value: value,
remainderPath: parts.join('/')
})
}
}
node = value
}
node = value
}
})
}

/*
* tree: returns a flattened array with paths: values of the project. options
* are option (i.e. nestness)
*/
exports.tree = (block, options) => {
exports.tree = (block, options, callback) => {
if (typeof options === 'function') {
callback = options
options = undefined
}

if (!options) {
options = {}
}

const node = util.deserialize(block.data)
return flattenObject(node)
util.deserialize(block.data, (err, node) => {
if (err) {
return callback(err)
}

callback(null, flattenObject(node))
})
}

// TODO recheck this API
Expand Down
10 changes: 5 additions & 5 deletions src/util.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const cbor = require('cbor-sync')
const cbor = require('cbor')
const multihashing = require('multihashing')
const CID = require('cids')
const resolver = require('./resolver')
Expand All @@ -11,12 +11,12 @@ exports.serialize = (dagNode) => {
return cbor.encode(dagNode)
}

exports.deserialize = (data) => {
return cbor.decode(data)
exports.deserialize = (data, callback) => {
cbor.decodeFirst(data, callback)
}

exports.cid = (dagNode) => {
exports.cid = (dagNode, callback) => {
const serialized = exports.serialize(dagNode)
const mh = multihashing(serialized, 'sha2-256')
return new CID(1, resolver.multicodec, mh)
callback(null, new CID(1, resolver.multicodec, mh))
}
91 changes: 55 additions & 36 deletions test/resolver.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint max-nested-callbacks: ["error", 8] */
/* eslint-env mocha */
'use strict'

Expand Down Expand Up @@ -37,58 +38,76 @@ describe('IPLD format resolver (local)', () => {

describe('empty node', () => {
describe('resolver.resolve', () => {
it('root', () => {
const result = resolver.resolve(emptyNodeBlock, '/')
expect(result.value).to.be.eql({})
it('root', (done) => {
resolver.resolve(emptyNodeBlock, '/', (err, result) => {
expect(err).to.not.exist
expect(result.value).to.be.eql({})
done()
})
})
})

it('resolver.tree', () => {
const paths = resolver.tree(emptyNodeBlock)
expect(paths).to.eql([])
it('resolver.tree', (done) => {
resolver.tree(emptyNodeBlock, (err, paths) => {
expect(err).to.not.exist
expect(paths).to.eql([])
done()
})
})

it.skip('resolver.patch', (done) => {})
it.skip('resolver.patch', () => {})
})

describe('node', () => {
describe('resolver.resolve', () => {
it('path within scope', () => {
const result = resolver.resolve(nodeBlock, 'name')
expect(result.value).to.equal('I am a node')
it('path within scope', (done) => {
resolver.resolve(nodeBlock, 'name', (err, result) => {
expect(err).to.not.exist
expect(result.value).to.equal('I am a node')
done()
})
})

it('path within scope, but nested', () => {
const result = resolver.resolve(nodeBlock, 'nest/foo/bar')
expect(result.value).to.equal('baz')
it('path within scope, but nested', (done) => {
resolver.resolve(nodeBlock, 'nest/foo/bar', (err, result) => {
expect(err).to.not.exist
expect(result.value).to.equal('baz')
done()
})
})

it('path out of scope', () => {
const result = resolver.resolve(nodeBlock, 'someLink/a/b/c')
expect(result.value).to.eql({ '/': 'LINK' })
expect(result.remainderPath).to.equal('a/b/c')
it('path out of scope', (done) => {
resolver.resolve(nodeBlock, 'someLink/a/b/c', (err, result) => {
expect(err).to.not.exist
expect(result.value).to.eql({ '/': 'LINK' })
expect(result.remainderPath).to.equal('a/b/c')
done()
})
})
})

it('resolver.tree', () => {
const paths = resolver.tree(nodeBlock)
expect(paths).to.eql([{
path: 'name',
value: 'I am a node'
}, {
// TODO: confirm how to represent links in tree
path: 'someLink//',
value: 'LINK'
}, {
path: 'nest/foo/bar',
value: 'baz'
}, {
path: 'array/0/a',
value: 'b'
}, {
path: 'array/1',
value: 2
}])
it('resolver.tree', (done) => {
resolver.tree(nodeBlock, (err, paths) => {
expect(err).to.not.exist
expect(paths).to.eql([{
path: 'name',
value: 'I am a node'
}, {
// TODO: confirm how to represent links in tree
path: 'someLink//',
value: 'LINK'
}, {
path: 'nest/foo/bar',
value: 'baz'
}, {
path: 'array/0/a',
value: 'b'
}, {
path: 'array/1',
value: 2
}])
done()
})
})

it.skip('resolver.patch', () => {})
Expand Down
22 changes: 14 additions & 8 deletions test/util.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,24 @@ describe('util', () => {
link: { '/': 'aaaaa' }
}

it('.serialize and .deserialize', () => {
it('.serialize and .deserialize', (done) => {
const serialized = dagCBOR.util.serialize(obj)
expect(Buffer.isBuffer(serialized)).to.be.true

const deserialized = dagCBOR.util.deserialize(serialized)
expect(obj).to.eql(deserialized)
dagCBOR.util.deserialize(serialized, (err, deserialized) => {
expect(err).to.not.exist
expect(obj).to.eql(deserialized)
done()
})
})

it('.cid', () => {
const cid = dagCBOR.util.cid(obj)
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('dag-cbor')
expect(cid.multihash).to.exist
it('.cid', (done) => {
dagCBOR.util.cid(obj, (err, cid) => {
expect(err).to.not.exist
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('dag-cbor')
expect(cid.multihash).to.exist
done()
})
})
})

0 comments on commit 48eb863

Please sign in to comment.