Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor for multiformats #2

Merged
merged 12 commits into from
Jun 13, 2020
25 changes: 25 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
on: [push, pull_request]
name: Build, test and maybe publish
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Cache node_modules
id: cache-modules
uses: actions/cache@v1
with:
path: node_modules
key: ${{ runner.OS }}-build-${{ hashFiles('package.json') }}
- name: Build
if: steps.cache-modules.outputs.cache-hit != 'true'
run: npm install
- name: Test
run: npm test
- name: Publish
if: github.ref == 'refs/heads/master' && github.repository == 'ipld/js-dag-cbor'
uses: mikeal/merge-release@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
docs
package-lock.json
yarn.lock
.nyc_output
# Logs
logs
*.log
Expand Down
40 changes: 0 additions & 40 deletions .travis.yml

This file was deleted.

132 changes: 132 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import cbor from 'borc'
import isCircular from 'is-circular'

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

const code = 0x71
const name = 'dag-cbor'

const create = multiformats => {
const { CID, bytes, varint } = multiformats
function tagCID (cid) {
const buffer = Uint8Array.from([...bytes.fromHex('00'), ...cid.buffer])
return new cbor.Tagged(CID_CBOR_TAG, buffer)
}

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

function transform (obj) {
if (bytes.isBinary(obj)) return bytes.coerce(obj)
if (!obj || typeof obj === 'string') {
return obj
}

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

if (CID.isCID(obj)) {
return tagCID(obj)
}

const keys = Object.keys(obj)

if (keys.length > 0) {
// Recursive transform
const 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)
}

const defaultTags = {
[CID_CBOR_TAG]: (val) => {
// remove that 0
val = Uint8Array.from(val.slice(1))
const [version] = varint.decode(val)
if (version > 1) {
// CIDv0
return new CID(0, 0x70, val)
}
return new CID(val)
}
}
const defaultSize = 64 * 1024 // current decoder heap size, 64 Kb
let currentSize = defaultSize
const defaultMaxSize = 64 * 1024 * 1024 // max heap size when auto-growing, 64 Mb
let maxSize = defaultMaxSize
let decoder = null

/**
* Configure the underlying CBOR decoder.
*
* @param {Object} [options] - The options the decoder takes. The decoder will reset to the defaul values if no options are given.
* @param {number} [options.size=65536] - The current heap size used in CBOR parsing, this may grow automatically as larger blocks are encountered up to `maxSize`
* @param {number} [options.maxSize=67108864] - The maximum size the CBOR parsing heap is allowed to grow to before `dagCBOR.util.deserialize()` returns an error
* @param {Object} [options.tags] - An object whose keys are CBOR tag numbers and values are transform functions that accept a `value` and return a decoded representation of that `value`
*/
const configureDecoder = (options) => {
const tags = defaultTags

if (options) {
if (typeof options.size === 'number') {
currentSize = options.size
}
if (typeof options.maxSize === 'number') {
maxSize = options.maxSize
}
} else {
// no options, reset to defaults
currentSize = defaultSize
maxSize = defaultMaxSize
}

const decoderOptions = {
tags,
size: currentSize
}

decoder = new cbor.Decoder(decoderOptions)
// borc edits opts.size in-place so we can capture _actual_ size
currentSize = decoderOptions.size
}
configureDecoder()
create.configureDecoder = configureDecoder // for testing

const encode = (node) => {
const nodeTagged = replaceCIDbyTAG(node)
const serialized = cbor.encode(nodeTagged)
return serialized
}

const decode = (data) => {
if (data.length > currentSize && data.length <= maxSize) {
configureDecoder({ size: data.length })
}

if (data.length > currentSize) {
throw new Error('Data is too large to deserialize with current decoder')
}

const deserialized = decoder.decodeFirst(data)
return deserialized
}

return { encode, decode, code, name }
}
export default create
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.0.0",
"description": "JS implementation of dag-cbor",
"main": "src/index.js",
"type": "module",
"scripts": {
"test": "hundreds mocha test/test-*.js && npm run test:browser",
"test:browser": "polendina --cleanup test/test-*.js",
Expand All @@ -26,8 +27,10 @@
"is-circular": "^1.0.2"
},
"devDependencies": {
"hundreds": "0.0.2",
"mocha": "^7.1.2",
"garbage": "0.0.0",
"hundreds": "0.0.4",
"mocha": "^8.0.1",
"multiformats": "1.0.7",
"polendina": "^1.0.0",
"standard": "^14.3.4"
},
Expand Down
6 changes: 0 additions & 6 deletions src/index.js

This file was deleted.

70 changes: 0 additions & 70 deletions src/resolver.js

This file was deleted.

Loading