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

Commit

Permalink
feat: CBOR TAG (#38)
Browse files Browse the repository at this point in the history
* feat: CBOR TAG
  • Loading branch information
daviddias committed Jan 31, 2017
1 parent 48f0294 commit 13323a2
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 18 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,16 @@
"borc": "^2.0.2",
"bs58": "^4.0.0",
"cids": "^0.4.0",
"is-circular": "^1.0.1",
"multihashes": "^0.3.2",
"multihashing-async": "^0.4.0",
"traverse": "^0.6.6"
},
"devDependencies": {
"aegir": "^9.4.0",
"chai": "^3.5.0",
"deep-freeze": "0.0.1",
"garbage": "0.0.0",
"ipfs-block": "^0.5.4",
"pre-commit": "^1.2.2"
},
Expand All @@ -59,4 +62,4 @@
"npmcdn-to-unpkg-bot <npmcdn-to-unpkg-bot@users.noreply.github.com>",
"wanderer <mjbecze@gmail.com>"
]
}
}
83 changes: 67 additions & 16 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,90 @@ const multihashing = require('multihashing-async')
const CID = require('cids')
const waterfall = require('async/waterfall')
const setImmediate = require('async/setImmediate')
const isCircular = require('is-circular')

const resolver = require('./resolver')

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

function tagCID (cid) {
return new cbor.Tagged(CID_CBOR_TAG, cid)
}

const decoder = new cbor.Decoder({
tags: {
[CID_CBOR_TAG]: (val) => ({'/': val})
}
})

function replaceCIDbyTAG (dagNode) {
if (isCircular(dagNode)) {
throw new Error('The object passed has circular references')
}

function transform (obj) {
if (!obj || Buffer.isBuffer(obj) || typeof obj === 'string') {
return obj
}

if (Array.isArray(obj)) {
return obj.map(transform)
}

const keys = Object.keys(obj)

// only `{'/': 'link'}` are valid
if (keys.length === 1 && keys[0] === '/') {
// Multiaddr encoding
// if (typeof link === 'string' && isMultiaddr(link)) {
// link = new Multiaddr(link).buffer
// }

return tagCID(obj['/'])
} else if (keys.length > 0) {
// Recursive transform
let out = {}
keys.forEach((key) => {
if (typeof obj[key] === 'object') {
out[key] = transform(obj[key])
} else {
out[key] = obj[key]
}
})
return out
} else {
return obj
}
}

return transform(dagNode)
}

exports = module.exports

exports.serialize = (dagNode, callback) => {
let serialized

try {
serialized = cbor.encode(dagNode)
const dagNodeTagged = replaceCIDbyTAG(dagNode)
serialized = cbor.encode(dagNodeTagged)
} catch (err) {
// return is important, otherwise in case of error the execution would continue
return setImmediate(() => {
callback(err)
})
return setImmediate(() => callback(err))
}
setImmediate(() => {
callback(null, serialized)
})
setImmediate(() => callback(null, serialized))
}

exports.deserialize = (data, callback) => {
let res
let deserialized

try {
res = cbor.decodeFirst(data)
deserialized = decoder.decodeFirst(data)
} catch (err) {
return setImmediate(() => {
callback(err)
})
return setImmediate(() => callback(err))
}

setImmediate(() => {
callback(null, res)
})
setImmediate(() => callback(null, deserialized))
}

exports.cid = (dagNode, callback) => {
Expand Down
43 changes: 42 additions & 1 deletion test/util.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,35 @@
'use strict'

const expect = require('chai').expect
const deepFreeze = require('deep-freeze')
const garbage = require('garbage')
const map = require('async/map')
const dagCBOR = require('../src')

describe('util', () => {
const obj = {
someKey: 'someValue',
link: { '/': 'aaaaa' }
link: { '/': 'aaaaa' },
links: [{'/': 1}, {'/': 2}],
nested: {
hello: 'world',
link: { '/': 'mylink' }
}
}

it('.serialize and .deserialize', (done) => {
// freeze, to ensure we don't change the source objecdt
deepFreeze(obj)
dagCBOR.util.serialize(obj, (err, serialized) => {
expect(err).to.not.exist
expect(Buffer.isBuffer(serialized)).to.be.true

// Check for the tag 42
// d8 = tag, 2a = 42
expect(
serialized.toString('hex').match(/d82a/g)
).to.have.length(4)

dagCBOR.util.deserialize(serialized, (err, deserialized) => {
expect(err).to.not.exist
expect(obj).to.eql(deserialized)
Expand Down Expand Up @@ -42,4 +58,29 @@ describe('util', () => {
done()
})
})

it('serialize and deserialize - garbage', (done) => {
const inputs = []
for (let i = 0; i < 1000; i++) {
inputs.push({in: garbage(100)})
}

map(inputs, (input, cb) => {
dagCBOR.util.serialize(input, cb)
}, (err, encoded) => {
if (err) {
return done(err)
}
map(encoded, (enc, cb) => {
dagCBOR.util.deserialize(enc, cb)
}, (err, out) => {
if (err) {
return done(err)
}

expect(inputs).to.be.eql(out)
done()
})
})
})
})

0 comments on commit 13323a2

Please sign in to comment.