From a349c9e1285c769ebd69da8e669834a89c78f370 Mon Sep 17 00:00:00 2001 From: David Dias Date: Tue, 31 Jan 2017 09:36:14 +0000 Subject: [PATCH] feat: CBOR TAG --- package.json | 6 +++- src/util.js | 96 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 85 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index d319c41..ba17000 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,10 @@ "borc": "^2.0.2", "bs58": "^4.0.0", "cids": "^0.4.0", + "is-circular": "^1.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.defaults": "^4.2.0", + "lodash.includes": "^4.3.0", "multihashes": "^0.3.2", "multihashing-async": "^0.4.0", "traverse": "^0.6.6" @@ -59,4 +63,4 @@ "npmcdn-to-unpkg-bot ", "wanderer " ] -} \ No newline at end of file +} diff --git a/src/util.js b/src/util.js index c49bae8..9cd21c7 100644 --- a/src/util.js +++ b/src/util.js @@ -5,39 +5,103 @@ const multihashing = require('multihashing-async') const CID = require('cids') const waterfall = require('async/waterfall') const setImmediate = require('async/setImmediate') +const cloneDeep = require('lodash.cloneDeep') +const includes = require('lodash.includes') +const defaults = require('lodash.defaults') +const isCircular = require('is-circular') const resolver = require('./resolver') +function tagCID (cid) { + // https://github.com/ipfs/go-ipfs/issues/3570#issuecomment-273931692 + const CID_CBOR_TAG = 42 + + return new cbor.Tagged(CID_CBOR_TAG, cid) +} + +function replaceCIDbyTAG (dagNode) { + if (isCircular(dagNode)) { + throw new Error('The object passes has circular references') + } + + const copy = cloneDeep(dagNode) + + function transform (obj) { + const keys = Object.keys(obj) + + // Recursive transform + keys.forEach((key) => { + if (typeof obj[key] === 'object') { + obj[key] = transform(obj[key]) + } + }) + + if (includes(keys, '/')) { + let cid = obj['/'] + + // Multiaddr encoding + // if (typeof link === 'string' && isMultiaddr(link)) { + // link = new Multiaddr(link).buffer + // } + + delete obj['/'] // Remove the / + return tagCID(cid) + } + + return obj + } + + return transform(copy) +} + +function replaceTAGbyCID (dagNode) { + function transform (obj) { + Object.keys(obj).forEach((key) => { + const val = obj[key] + + if (val instanceof cbor.Tagged) { + if (typeof val.value === 'string') { + obj[key] = { '/': val.value } + } else { + obj[key] = defaults({ '/': val.value[0] }, transform(val.value[1])) + } + } else if (typeof val === 'object') { + obj[key] = transform(val) + } + }) + + 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 = cbor.decodeFirst(data) } catch (err) { - return setImmediate(() => { - callback(err) - }) + return setImmediate(() => callback(err)) } - setImmediate(() => { - callback(null, res) - }) + const dagNode = replaceTAGbyCID(deserialized) + + setImmediate(() => callback(null, dagNode)) } exports.cid = (dagNode, callback) => {