Initial commit
This commit is contained in:
30
node_modules/cbor/lib/cbor.js
generated
vendored
Normal file
30
node_modules/cbor/lib/cbor.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
'use strict'
|
||||
|
||||
exports.Commented = require('./commented')
|
||||
exports.Diagnose = require('./diagnose')
|
||||
exports.Decoder = require('./decoder')
|
||||
exports.Encoder = require('./encoder')
|
||||
exports.Simple = require('./simple')
|
||||
exports.Tagged = require('./tagged')
|
||||
exports.Map = require('./map')
|
||||
|
||||
exports.comment = exports.Commented.comment
|
||||
exports.decodeAll = exports.Decoder.decodeAll
|
||||
exports.decodeFirst = exports.Decoder.decodeFirst
|
||||
exports.decodeAllSync = exports.Decoder.decodeAllSync
|
||||
exports.decodeFirstSync = exports.Decoder.decodeFirstSync
|
||||
exports.diagnose = exports.Diagnose.diagnose
|
||||
exports.encode = exports.Encoder.encode
|
||||
exports.encodeCanonical = exports.Encoder.encodeCanonical
|
||||
exports.encodeOne = exports.Encoder.encodeOne
|
||||
exports.encodeAsync = exports.Encoder.encodeAsync
|
||||
exports.decode = exports.Decoder.decodeFirstSync
|
||||
|
||||
exports.leveldb = {
|
||||
decode: exports.Decoder.decodeAllSync,
|
||||
encode: exports.Encoder.encode,
|
||||
buffer: true,
|
||||
name: 'cbor'
|
||||
}
|
||||
|
||||
exports.hasBigInt = require('./utils').hasBigInt
|
||||
345
node_modules/cbor/lib/commented.js
generated
vendored
Normal file
345
node_modules/cbor/lib/commented.js
generated
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
'use strict'
|
||||
|
||||
const stream = require('stream')
|
||||
const util = require('util')
|
||||
const utils = require('./utils')
|
||||
const Simple = require('./simple')
|
||||
const Decoder = require('./decoder')
|
||||
const constants = require('./constants')
|
||||
const bignumber = require('bignumber.js').BigNumber
|
||||
const NoFilter = require('nofilter')
|
||||
|
||||
const MT = constants.MT
|
||||
const NUMBYTES = constants.NUMBYTES
|
||||
const SYMS = constants.SYMS
|
||||
|
||||
function plural(c) {
|
||||
if (c > 1) {
|
||||
return 's'
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the expanded format of RFC 7049, section 2.2.1
|
||||
*
|
||||
* @extends {stream.Transform}
|
||||
*/
|
||||
class Commented extends stream.Transform {
|
||||
/**
|
||||
* Create a CBOR commenter.
|
||||
*
|
||||
* @param {object} [options={}] - Stream options
|
||||
* @param {number} [options.max_depth=10] - how many times to indent
|
||||
* the dashes
|
||||
*/
|
||||
constructor(options) {
|
||||
const opts = Object.assign({
|
||||
max_depth: 10
|
||||
}, options, {
|
||||
readableObjectMode: false,
|
||||
writableObjectMode: false
|
||||
})
|
||||
const max_depth = opts.max_depth
|
||||
delete opts.max_depth
|
||||
super(opts)
|
||||
|
||||
this.depth = 1
|
||||
this.max_depth = max_depth
|
||||
this.all = new NoFilter()
|
||||
this.parser = new Decoder(opts)
|
||||
this.parser.on('value', this._on_value.bind(this))
|
||||
this.parser.on('start', this._on_start.bind(this))
|
||||
this.parser.on('start-string', this._on_start_string.bind(this))
|
||||
this.parser.on('stop', this._on_stop.bind(this))
|
||||
this.parser.on('more-bytes', this._on_more.bind(this))
|
||||
this.parser.on('error', this._on_error.bind(this))
|
||||
this.parser.on('data', this._on_data.bind(this))
|
||||
this.parser.bs.on('read', this._on_read.bind(this))
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_transform(fresh, encoding, cb) {
|
||||
this.parser.write(fresh, encoding, cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_flush(cb) {
|
||||
// TODO: find the test that covers this, and look at the return value
|
||||
return this.parser._flush(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* @callback commentCallback
|
||||
* @param {Error} [error] - if one was generated
|
||||
* @param {string} [commented] - the comment string
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef CommentOptions
|
||||
* @property {number} [max_depth=10] how many times to indent the dashes
|
||||
* @property {string} [encoding='hex'] encoding of the input
|
||||
*/
|
||||
/**
|
||||
* Comment on an input Buffer or string, creating a string passed to the
|
||||
* callback. If callback not specified, a promise is returned.
|
||||
*
|
||||
* @static
|
||||
* @param {string|Buffer} input
|
||||
* @param {CommentOptions|commentCallback|string} [options] or callback
|
||||
* @param {commentCallback=} cb
|
||||
* @returns {Promise} if cb not specified
|
||||
*/
|
||||
static comment(input, options, cb) {
|
||||
if (input == null) {
|
||||
throw new Error('input required')
|
||||
}
|
||||
let encoding = (typeof input === 'string') ? 'hex' : void 0
|
||||
let max_depth = 10
|
||||
switch (typeof options) {
|
||||
case 'function':
|
||||
cb = options
|
||||
break
|
||||
case 'string':
|
||||
encoding = options
|
||||
break
|
||||
case 'number':
|
||||
max_depth = options
|
||||
break
|
||||
case 'object':
|
||||
const ref1 = options.encoding
|
||||
const ref2 = options.max_depth
|
||||
encoding = (ref1 != null) ? ref1 : encoding
|
||||
max_depth = (ref2 != null) ? ref2 : max_depth
|
||||
break
|
||||
case 'undefined':
|
||||
break
|
||||
default:
|
||||
throw new Error('Unknown option type')
|
||||
}
|
||||
const bs = new NoFilter()
|
||||
const d = new Commented({
|
||||
max_depth
|
||||
})
|
||||
let p = null
|
||||
if (typeof cb === 'function') {
|
||||
d.on('end', () => {
|
||||
cb(null, bs.toString('utf8'))
|
||||
})
|
||||
d.on('error', cb)
|
||||
} else {
|
||||
p = new Promise((resolve, reject) => {
|
||||
d.on('end', () => {
|
||||
resolve(bs.toString('utf8'))
|
||||
})
|
||||
return d.on('error', reject)
|
||||
})
|
||||
}
|
||||
d.pipe(bs)
|
||||
d.end(input, encoding)
|
||||
return p
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_on_error(er) {
|
||||
return this.push('ERROR: ') &&
|
||||
this.push(er.toString()) &&
|
||||
this.push('\n')
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_on_read(buf) {
|
||||
this.all.write(buf)
|
||||
const hex = buf.toString('hex')
|
||||
this.push(new Array(this.depth + 1).join(' '))
|
||||
this.push(hex)
|
||||
let ind = (this.max_depth - this.depth) * 2
|
||||
ind -= hex.length
|
||||
if (ind < 1) {
|
||||
ind = 1
|
||||
}
|
||||
this.push(new Array(ind + 1).join(' '))
|
||||
return this.push('-- ')
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_on_more(mt, len, parent_mt, pos) {
|
||||
this.depth++
|
||||
let desc = ''
|
||||
switch (mt) {
|
||||
case MT.POS_INT:
|
||||
desc = 'Positive number,'
|
||||
break
|
||||
case MT.NEG_INT:
|
||||
desc = 'Negative number,'
|
||||
break
|
||||
case MT.ARRAY:
|
||||
desc = 'Array, length'
|
||||
break
|
||||
case MT.MAP:
|
||||
desc = 'Map, count'
|
||||
break
|
||||
case MT.BYTE_STRING:
|
||||
desc = 'Bytes, length'
|
||||
break
|
||||
case MT.UTF8_STRING:
|
||||
desc = 'String, length'
|
||||
break
|
||||
case MT.SIMPLE_FLOAT:
|
||||
if (len === 1) {
|
||||
desc = 'Simple value,'
|
||||
} else {
|
||||
desc = 'Float,'
|
||||
}
|
||||
break
|
||||
}
|
||||
return this.push(desc + ' next ' + len + ' byte' + (plural(len)) + '\n')
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_on_start_string(mt, tag, parent_mt, pos) {
|
||||
this.depth++
|
||||
let desc = ''
|
||||
switch (mt) {
|
||||
case MT.BYTE_STRING:
|
||||
desc = 'Bytes, length: ' + tag
|
||||
break
|
||||
case MT.UTF8_STRING:
|
||||
desc = 'String, length: ' + (tag.toString())
|
||||
break
|
||||
}
|
||||
return this.push(desc + '\n')
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_on_start(mt, tag, parent_mt, pos) {
|
||||
this.depth++
|
||||
if (tag !== SYMS.BREAK) {
|
||||
switch (parent_mt) {
|
||||
case MT.ARRAY:
|
||||
this.push(`[${pos}], `)
|
||||
break
|
||||
case MT.MAP:
|
||||
if (pos % 2) {
|
||||
this.push(`{Val:${Math.floor(pos / 2)}}, `)
|
||||
} else {
|
||||
this.push(`{Key:${Math.floor(pos / 2)}}, `)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
switch (mt) {
|
||||
case MT.TAG:
|
||||
this.push(`Tag #${tag}`)
|
||||
break
|
||||
case MT.ARRAY:
|
||||
if (tag === SYMS.STREAM) {
|
||||
this.push('Array (streaming)')
|
||||
} else {
|
||||
this.push(`Array, ${tag} item${plural(tag)}`)
|
||||
}
|
||||
break
|
||||
case MT.MAP:
|
||||
if (tag === SYMS.STREAM) {
|
||||
this.push('Map (streaming)')
|
||||
} else {
|
||||
this.push(`Map, ${tag} pair${plural(tag)}`)
|
||||
}
|
||||
break
|
||||
case MT.BYTE_STRING:
|
||||
this.push('Bytes (streaming)')
|
||||
break
|
||||
case MT.UTF8_STRING:
|
||||
this.push('String (streaming)')
|
||||
break
|
||||
}
|
||||
return this.push('\n')
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_on_stop(mt) {
|
||||
return this.depth--
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_on_value(val, parent_mt, pos, ai) {
|
||||
if (val !== SYMS.BREAK) {
|
||||
switch (parent_mt) {
|
||||
case MT.ARRAY:
|
||||
this.push(`[${pos}], `)
|
||||
break
|
||||
case MT.MAP:
|
||||
if (pos % 2) {
|
||||
this.push(`{Val:${Math.floor(pos / 2)}}, `)
|
||||
} else {
|
||||
this.push(`{Key:${Math.floor(pos / 2)}}, `)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (val === SYMS.BREAK) {
|
||||
this.push('BREAK\n')
|
||||
} else if (val === SYMS.NULL) {
|
||||
this.push('null\n')
|
||||
} else if (val === SYMS.UNDEFINED) {
|
||||
this.push('undefined\n')
|
||||
} else if (typeof val === 'string') {
|
||||
this.depth--
|
||||
if (val.length > 0 ) {
|
||||
this.push(JSON.stringify(val))
|
||||
this.push('\n')
|
||||
}
|
||||
} else if (Buffer.isBuffer(val)) {
|
||||
this.depth--
|
||||
if (val.length > 0) {
|
||||
this.push(val.toString('hex'))
|
||||
this.push('\n')
|
||||
}
|
||||
} else if (val instanceof bignumber) {
|
||||
this.push(val.toString())
|
||||
this.push('\n')
|
||||
} else {
|
||||
this.push(util.inspect(val))
|
||||
this.push('\n')
|
||||
}
|
||||
|
||||
switch (ai) {
|
||||
case NUMBYTES.ONE:
|
||||
case NUMBYTES.TWO:
|
||||
case NUMBYTES.FOUR:
|
||||
case NUMBYTES.EIGHT:
|
||||
this.depth--
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_on_data() {
|
||||
this.push('0x')
|
||||
this.push(this.all.read().toString('hex'))
|
||||
return this.push('\n')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Commented
|
||||
75
node_modules/cbor/lib/constants.js
generated
vendored
Normal file
75
node_modules/cbor/lib/constants.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
'use strict'
|
||||
const bignumber = require('bignumber.js').BigNumber
|
||||
|
||||
exports.MT = {
|
||||
POS_INT: 0,
|
||||
NEG_INT: 1,
|
||||
BYTE_STRING: 2,
|
||||
UTF8_STRING: 3,
|
||||
ARRAY: 4,
|
||||
MAP: 5,
|
||||
TAG: 6,
|
||||
SIMPLE_FLOAT: 7
|
||||
}
|
||||
|
||||
exports.TAG = {
|
||||
DATE_STRING: 0,
|
||||
DATE_EPOCH: 1,
|
||||
POS_BIGINT: 2,
|
||||
NEG_BIGINT: 3,
|
||||
DECIMAL_FRAC: 4,
|
||||
BIGFLOAT: 5,
|
||||
BASE64URL_EXPECTED: 21,
|
||||
BASE64_EXPECTED: 22,
|
||||
BASE16_EXPECTED: 23,
|
||||
CBOR: 24,
|
||||
URI: 32,
|
||||
BASE64URL: 33,
|
||||
BASE64: 34,
|
||||
REGEXP: 35,
|
||||
MIME: 36
|
||||
}
|
||||
|
||||
exports.NUMBYTES = {
|
||||
ZERO: 0,
|
||||
ONE: 24,
|
||||
TWO: 25,
|
||||
FOUR: 26,
|
||||
EIGHT: 27,
|
||||
INDEFINITE: 31
|
||||
}
|
||||
|
||||
exports.SIMPLE = {
|
||||
FALSE: 20,
|
||||
TRUE: 21,
|
||||
NULL: 22,
|
||||
UNDEFINED: 23
|
||||
}
|
||||
|
||||
exports.SYMS = {
|
||||
NULL: Symbol('null'),
|
||||
UNDEFINED: Symbol('undef'),
|
||||
PARENT: Symbol('parent'),
|
||||
BREAK: Symbol('break'),
|
||||
STREAM: Symbol('stream')
|
||||
}
|
||||
|
||||
exports.SHIFT32 = 0x100000000
|
||||
|
||||
exports.BI = {
|
||||
MINUS_ONE: -1,
|
||||
MAXINT32: 0xffffffff,
|
||||
MAXINT64: '0xffffffffffffffff',
|
||||
SHIFT32: exports.SHIFT32
|
||||
}
|
||||
|
||||
const MINUS_ONE = new bignumber(-1)
|
||||
exports.BN = {
|
||||
MINUS_ONE,
|
||||
NEG_MAX: MINUS_ONE.minus(
|
||||
new bignumber(Number.MAX_SAFE_INTEGER.toString(16), 16)),
|
||||
MAXINT: new bignumber('0x20000000000000'),
|
||||
MAXINT32: new bignumber(0xffffffff),
|
||||
MAXINT64: new bignumber('0xffffffffffffffff'),
|
||||
SHIFT32: new bignumber(exports.SHIFT32)
|
||||
}
|
||||
574
node_modules/cbor/lib/decoder.js
generated
vendored
Normal file
574
node_modules/cbor/lib/decoder.js
generated
vendored
Normal file
@@ -0,0 +1,574 @@
|
||||
'use strict'
|
||||
|
||||
const stream = require('stream')
|
||||
const BinaryParseStream = require('../vendor/binary-parse-stream')
|
||||
const Tagged = require('./tagged')
|
||||
const Simple = require('./simple')
|
||||
const utils = require('./utils')
|
||||
const bignumber = require('bignumber.js').BigNumber
|
||||
const NoFilter = require('nofilter')
|
||||
const constants = require('./constants')
|
||||
// Do not fix this if you want to support node v4
|
||||
const MT = constants.MT
|
||||
const NUMBYTES = constants.NUMBYTES
|
||||
const SIMPLE = constants.SIMPLE
|
||||
const SYMS = constants.SYMS
|
||||
|
||||
const BI = utils.bigIntize(constants.BI)
|
||||
const BN = constants.BN
|
||||
const COUNT = Symbol('count')
|
||||
const PENDING_KEY = Symbol('pending_key')
|
||||
const MAJOR = Symbol('major type')
|
||||
const ERROR = Symbol('error')
|
||||
const NOT_FOUND = Symbol('not found')
|
||||
|
||||
function parentArray(parent, typ, count) {
|
||||
const a = []
|
||||
a[COUNT] = count
|
||||
a[SYMS.PARENT] = parent
|
||||
a[MAJOR] = typ
|
||||
return a
|
||||
}
|
||||
|
||||
function parentBufferStream(parent, typ) {
|
||||
const b = new NoFilter()
|
||||
b[COUNT] = -1
|
||||
b[SYMS.PARENT] = parent
|
||||
b[MAJOR] = typ
|
||||
return b
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Buffer} v
|
||||
* @private
|
||||
*/
|
||||
function _tag_2(v) {
|
||||
return utils.bufferToBigInt(v)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BigInt} v
|
||||
* @private
|
||||
*/
|
||||
function _tag_3(v) {
|
||||
// avoid syntax error on old runtimes
|
||||
return BI.MINUS_ONE - utils.bufferToBigInt(v)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a stream of CBOR bytes by transforming them into equivalent
|
||||
* JavaScript data. Because of the limitations of Node object streams,
|
||||
* special symbols are emitted instead of NULL or UNDEFINED. Fix those
|
||||
* up by calling {@link Decoder.nullcheck}.
|
||||
*
|
||||
* @extends {BinaryParseStream}
|
||||
*/
|
||||
class Decoder extends BinaryParseStream {
|
||||
|
||||
/**
|
||||
* Create a parsing stream.
|
||||
*
|
||||
* @param {object} [options={}]
|
||||
* @param {number} [options.max_depth=-1] - the maximum depth to parse.
|
||||
* Use -1 for "until you run out of memory". Set this to a finite
|
||||
* positive number for un-trusted inputs. Most standard inputs won't nest
|
||||
* more than 100 or so levels; I've tested into the millions before
|
||||
* running out of memory.
|
||||
* @param {object} [options.tags] - mapping from tag number to function(v),
|
||||
* where v is the decoded value that comes after the tag, and where the
|
||||
* function returns the correctly-created value for that tag.
|
||||
* @param {boolean} [options.bigint=false] generate JavaScript BigInt's
|
||||
* instead of BigNumbers, when possible. TODO: when BigInt's are
|
||||
* more prevalent, change this to default to the value of cbor.hasBigInt.
|
||||
*/
|
||||
constructor(options) {
|
||||
options = options || {}
|
||||
const tags = options.tags
|
||||
delete options.tags
|
||||
const max_depth = (options.max_depth != null) ? options.max_depth : -1
|
||||
delete options.max_depth
|
||||
const bigI = utils.hasBigInt ? (!!options.bigint) : false
|
||||
delete options.bigint
|
||||
super(options)
|
||||
|
||||
this.running = true
|
||||
this.max_depth = max_depth
|
||||
this.tags = tags
|
||||
if (bigI) {
|
||||
if (this.tags == null) {
|
||||
this.tags = {}
|
||||
}
|
||||
if (this.tags[2] == null) {
|
||||
this.tags[2] = _tag_2
|
||||
}
|
||||
if (this.tags[3] == null) {
|
||||
this.tags[3] = _tag_3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the given value for a symbol encoding a NULL or UNDEFINED value in
|
||||
* the CBOR stream.
|
||||
*
|
||||
* @static
|
||||
* @param {any} val - the value to check
|
||||
* @returns {any} the corrected value
|
||||
*
|
||||
* @example
|
||||
* myDecoder.on('data', function(val) {
|
||||
* val = Decoder.nullcheck(val);
|
||||
* ...
|
||||
* });
|
||||
*/
|
||||
static nullcheck(val) {
|
||||
switch (val) {
|
||||
case SYMS.NULL:
|
||||
return null
|
||||
case SYMS.UNDEFINED:
|
||||
return undefined
|
||||
case NOT_FOUND:
|
||||
throw new Error('Value not found')
|
||||
default:
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef DecodeOptions
|
||||
* @property {string} [encoding='hex'] - The encoding of the input.
|
||||
* Ignored if input is a Buffer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Decode the first CBOR item in the input, synchronously. This will throw an
|
||||
* exception if the input is not valid CBOR.
|
||||
*
|
||||
* @static
|
||||
* @param {string|Buffer|stream.Readable} input
|
||||
* @param {DecodeOptions|string} [options] Options
|
||||
* @returns {any} - the decoded value
|
||||
*/
|
||||
static decodeFirstSync(input, options) {
|
||||
options = options || { encoding: 'hex' }
|
||||
let opts = {}
|
||||
let encod
|
||||
switch (typeof options) {
|
||||
case 'string':
|
||||
encod = options
|
||||
break
|
||||
case 'object':
|
||||
opts = utils.extend({}, options)
|
||||
encod = opts.encoding
|
||||
delete opts.encoding
|
||||
break
|
||||
}
|
||||
const c = new Decoder(opts)
|
||||
const s = (input instanceof stream.Readable) ? input : new NoFilter(
|
||||
input,
|
||||
encod != null ? encod : utils.guessEncoding(input))
|
||||
|
||||
// for/of doesn't work when you need to call next() with a value
|
||||
// generator created by parser will be "done" after each CBOR entity
|
||||
// parser will yield numbers of bytes that it wants
|
||||
const parser = c._parse()
|
||||
let state = parser.next()
|
||||
while (!state.done) {
|
||||
const b = s.read(state.value)
|
||||
if ((b == null) || (b.length !== state.value)) {
|
||||
throw new Error('Insufficient data')
|
||||
}
|
||||
state = parser.next(b)
|
||||
}
|
||||
const val = Decoder.nullcheck(state.value)
|
||||
if (s.length > 0) {
|
||||
const nextByte = s.read(1)
|
||||
s.unshift(nextByte)
|
||||
const er = new Error(
|
||||
'Unexpected data: 0x' + nextByte[0].toString(16))
|
||||
er.value = val
|
||||
throw er
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode all of the CBOR items in the input into an array. This will throw
|
||||
* an exception if the input is not valid CBOR; a zero-length input will
|
||||
* return an empty array.
|
||||
*
|
||||
* @static
|
||||
* @param {string|Buffer|stream.Readable} input
|
||||
* @param {DecodeOptions|string} [options] Options or encoding string
|
||||
* @returns {Array} - Array of all found items
|
||||
*/
|
||||
static decodeAllSync(input, options) {
|
||||
options = options || { encoding: 'hex' }
|
||||
let opts = {}
|
||||
let encod
|
||||
switch (typeof options) {
|
||||
case 'string':
|
||||
encod = options
|
||||
break
|
||||
case 'object':
|
||||
opts = utils.extend({}, options)
|
||||
encod = opts.encoding
|
||||
delete opts.encoding
|
||||
}
|
||||
const c = new Decoder(opts)
|
||||
const s = (input instanceof stream.Readable) ? input : new NoFilter(
|
||||
input,
|
||||
encod != null ? encod : utils.guessEncoding(input))
|
||||
const res = []
|
||||
while (s.length > 0) {
|
||||
const parser = c._parse()
|
||||
let state = parser.next()
|
||||
while (!state.done) {
|
||||
const b = s.read(state.value)
|
||||
if ((b == null) || (b.length !== state.value)) {
|
||||
throw new Error('Insufficient data')
|
||||
}
|
||||
state = parser.next(b)
|
||||
}
|
||||
res.push(Decoder.nullcheck(state.value))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* @callback decodeCallback
|
||||
* @param {Error} [error] - if one was generated
|
||||
* @param {any} [value] - the decoded value
|
||||
*/
|
||||
|
||||
/**
|
||||
* Decode the first CBOR item in the input. This will error if there are more
|
||||
* bytes left over at the end, and optionally if there were no valid CBOR
|
||||
* bytes in the input. Emits the {Decoder.NOT_FOUND} Symbol in the callback
|
||||
* if no data was found and the `required` option is false.
|
||||
*
|
||||
* @static
|
||||
* @param {string|Buffer} input - the input to parse
|
||||
* @param {DecodeOptions|decodeCallback|string} [options] - options
|
||||
* @param {decodeCallback} [cb] callback
|
||||
* @returns {Promise<any>} returned even if callback is specified
|
||||
*/
|
||||
static decodeFirst(input, options, cb) {
|
||||
let opts = {}
|
||||
let required = false
|
||||
let encod = 'hex'
|
||||
switch (typeof options) {
|
||||
case 'function':
|
||||
cb = options
|
||||
encod = utils.guessEncoding(input)
|
||||
break
|
||||
case 'string':
|
||||
encod = options
|
||||
break
|
||||
case 'object':
|
||||
opts = utils.extend({}, options)
|
||||
encod = (opts.encoding != null) ?
|
||||
opts.encoding : utils.guessEncoding(input)
|
||||
delete opts.encoding
|
||||
required = (opts.required != null) ? opts.required : false
|
||||
delete opts.required
|
||||
}
|
||||
const c = new Decoder(opts)
|
||||
let v = NOT_FOUND
|
||||
const p = new Promise((resolve, reject) => {
|
||||
c.on('data', (val) => {
|
||||
v = Decoder.nullcheck(val)
|
||||
c.close()
|
||||
})
|
||||
c.once('error', (er) => {
|
||||
if (v !== NOT_FOUND) {
|
||||
er.value = v
|
||||
}
|
||||
v = ERROR
|
||||
c.close()
|
||||
return reject(er)
|
||||
})
|
||||
c.once('end', () => {
|
||||
switch (v) {
|
||||
case NOT_FOUND:
|
||||
if (required) {
|
||||
return reject(new Error('No CBOR found'))
|
||||
} else {
|
||||
return resolve(v)
|
||||
}
|
||||
case ERROR:
|
||||
return void 0
|
||||
default:
|
||||
return resolve(v)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (typeof cb === 'function') {
|
||||
p.then(v => cb(null, v), cb)
|
||||
}
|
||||
c.end(input, encod)
|
||||
return p
|
||||
}
|
||||
|
||||
/**
|
||||
* @callback decodeAllCallback
|
||||
* @param {Error} error - if one was generated
|
||||
* @param {Array} value - all of the decoded values, wrapped in an Array
|
||||
*/
|
||||
|
||||
/**
|
||||
* Decode all of the CBOR items in the input. This will error if there are
|
||||
* more bytes left over at the end.
|
||||
*
|
||||
* @static
|
||||
* @param {(string|Buffer)} input - the input to parse
|
||||
* @param {(string|Object)} options - Decoding options.
|
||||
* If string, the input encoding.
|
||||
* @param {decodeAllCallback} cb callback
|
||||
* @returns {Promise<Array>} even if callback is specified
|
||||
*/
|
||||
static decodeAll(input, options, cb) {
|
||||
let opts = {}
|
||||
let encod = 'hex'
|
||||
switch (typeof options) {
|
||||
case 'function':
|
||||
cb = options
|
||||
encod = utils.guessEncoding(input)
|
||||
break
|
||||
case 'string':
|
||||
encod = options
|
||||
break
|
||||
case 'object':
|
||||
opts = utils.extend({}, options)
|
||||
encod = (opts.encoding != null) ?
|
||||
opts.encoding : utils.guessEncoding(input)
|
||||
delete opts.encoding
|
||||
}
|
||||
const c = new Decoder(opts)
|
||||
const vals = []
|
||||
c.on('data', (val) => {
|
||||
return vals.push(Decoder.nullcheck(val))
|
||||
})
|
||||
const p = new Promise((resolve, reject) => {
|
||||
c.on('error', reject)
|
||||
c.on('end', () => resolve(vals))
|
||||
})
|
||||
if (typeof cb === 'function') {
|
||||
p.then(v => cb(null, v), cb)
|
||||
}
|
||||
c.end(input, encod)
|
||||
return p
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
*/
|
||||
close() {
|
||||
this.running = false
|
||||
this.__fresh = true
|
||||
}
|
||||
|
||||
*_parse() {
|
||||
let parent = null
|
||||
let depth = 0
|
||||
let val = null
|
||||
while (true) {
|
||||
if ((this.max_depth >= 0) && (depth > this.max_depth)) {
|
||||
throw new Error('Maximum depth ' + this.max_depth + ' exceeded')
|
||||
}
|
||||
const octet = (yield 1)[0]
|
||||
if (!this.running) {
|
||||
throw new Error('Unexpected data: 0x' + (octet.toString(16)))
|
||||
}
|
||||
const mt = octet >> 5
|
||||
const ai = octet & 0x1f
|
||||
const parent_major = (parent != null) ? parent[MAJOR] : undefined
|
||||
const parent_length = (parent != null) ? parent.length : undefined
|
||||
switch (ai) {
|
||||
case NUMBYTES.ONE:
|
||||
this.emit('more-bytes', mt, 1, parent_major, parent_length)
|
||||
val = (yield 1)[0]
|
||||
break
|
||||
case NUMBYTES.TWO:
|
||||
case NUMBYTES.FOUR:
|
||||
case NUMBYTES.EIGHT:
|
||||
const numbytes = 1 << (ai - 24)
|
||||
this.emit('more-bytes', mt, numbytes, parent_major, parent_length)
|
||||
const buf = yield numbytes
|
||||
val = (mt === MT.SIMPLE_FLOAT) ? buf : utils.parseCBORint(ai, buf)
|
||||
break
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
this.running = false
|
||||
throw new Error('Additional info not implemented: ' + ai)
|
||||
case NUMBYTES.INDEFINITE:
|
||||
switch (mt) {
|
||||
case MT.POS_INT:
|
||||
case MT.NEG_INT:
|
||||
case MT.TAG:
|
||||
throw new Error(`Invalid indefinite encoding for MT ${mt}`)
|
||||
}
|
||||
val = -1
|
||||
break
|
||||
default:
|
||||
val = ai
|
||||
}
|
||||
switch (mt) {
|
||||
case MT.POS_INT:
|
||||
// val already decoded
|
||||
break
|
||||
case MT.NEG_INT:
|
||||
if (val === Number.MAX_SAFE_INTEGER) {
|
||||
val = BN.NEG_MAX
|
||||
} else if (val instanceof bignumber) {
|
||||
val = BN.MINUS_ONE.minus(val)
|
||||
} else {
|
||||
val = -1 - val
|
||||
}
|
||||
break
|
||||
case MT.BYTE_STRING:
|
||||
case MT.UTF8_STRING:
|
||||
switch (val) {
|
||||
case 0:
|
||||
this.emit('start-string', mt, val, parent_major, parent_length)
|
||||
val = (mt === MT.BYTE_STRING) ? Buffer.allocUnsafe(0) : ''
|
||||
break
|
||||
case -1:
|
||||
this.emit('start', mt, SYMS.STREAM, parent_major, parent_length)
|
||||
parent = parentBufferStream(parent, mt)
|
||||
depth++
|
||||
continue
|
||||
default:
|
||||
this.emit('start-string', mt, val, parent_major, parent_length)
|
||||
val = yield val
|
||||
if (mt === MT.UTF8_STRING) {
|
||||
val = utils.utf8(val)
|
||||
}
|
||||
}
|
||||
break
|
||||
case MT.ARRAY:
|
||||
case MT.MAP:
|
||||
switch (val) {
|
||||
case 0:
|
||||
val = (mt === MT.MAP) ? {} : []
|
||||
break
|
||||
case -1:
|
||||
this.emit('start', mt, SYMS.STREAM, parent_major, parent_length)
|
||||
parent = parentArray(parent, mt, -1)
|
||||
depth++
|
||||
continue
|
||||
default:
|
||||
this.emit('start', mt, val, parent_major, parent_length)
|
||||
parent = parentArray(parent, mt, val * (mt - 3))
|
||||
depth++
|
||||
continue
|
||||
}
|
||||
break
|
||||
case MT.TAG:
|
||||
this.emit('start', mt, val, parent_major, parent_length)
|
||||
parent = parentArray(parent, mt, 1)
|
||||
parent.push(val)
|
||||
depth++
|
||||
continue
|
||||
case MT.SIMPLE_FLOAT:
|
||||
if (typeof val === 'number') {
|
||||
if ((ai === NUMBYTES.ONE) && (val < 32)) {
|
||||
throw new Error(
|
||||
`Invalid two-byte encoding of simple value ${val}`
|
||||
)
|
||||
}
|
||||
const hasParent = (parent != null)
|
||||
val = Simple.decode(
|
||||
val,
|
||||
hasParent,
|
||||
hasParent && (parent[COUNT] < 0))
|
||||
} else {
|
||||
val = utils.parseCBORfloat(val)
|
||||
}
|
||||
}
|
||||
this.emit('value', val, parent_major, parent_length, ai)
|
||||
let again = false
|
||||
while (parent != null) {
|
||||
switch (false) {
|
||||
case val !== SYMS.BREAK:
|
||||
parent[COUNT] = 1
|
||||
break
|
||||
case !Array.isArray(parent):
|
||||
parent.push(val)
|
||||
break
|
||||
case !(parent instanceof NoFilter):
|
||||
const pm = parent[MAJOR]
|
||||
if ((pm != null) && (pm !== mt)) {
|
||||
this.running = false
|
||||
throw new Error('Invalid major type in indefinite encoding')
|
||||
}
|
||||
parent.write(val)
|
||||
}
|
||||
if ((--parent[COUNT]) !== 0) {
|
||||
again = true
|
||||
break
|
||||
}
|
||||
--depth
|
||||
delete parent[COUNT]
|
||||
this.emit('stop', parent[MAJOR])
|
||||
|
||||
if (Array.isArray(parent)) {
|
||||
switch (parent[MAJOR]) {
|
||||
case MT.ARRAY:
|
||||
val = parent
|
||||
break
|
||||
case MT.MAP:
|
||||
let allstrings = true
|
||||
if ((parent.length % 2) !== 0) {
|
||||
throw new Error('Invalid map length: ' + parent.length)
|
||||
}
|
||||
for (let i = 0, len = parent.length; i < len; i += 2) {
|
||||
if (typeof parent[i] !== 'string') {
|
||||
allstrings = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (allstrings) {
|
||||
val = {}
|
||||
for (let i = 0, len = parent.length; i < len; i += 2) {
|
||||
val[parent[i]] = parent[i + 1]
|
||||
}
|
||||
} else {
|
||||
val = new Map
|
||||
for (let i = 0, len = parent.length; i < len; i += 2) {
|
||||
val.set(parent[i], parent[i + 1])
|
||||
}
|
||||
}
|
||||
break
|
||||
case MT.TAG:
|
||||
const t = new Tagged(parent[0], parent[1])
|
||||
val = t.convert(this.tags)
|
||||
break
|
||||
}
|
||||
} else if (parent instanceof NoFilter) {
|
||||
switch (parent[MAJOR]) {
|
||||
case MT.BYTE_STRING:
|
||||
val = parent.slice()
|
||||
break
|
||||
case MT.UTF8_STRING:
|
||||
val = parent.toString('utf-8')
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const old = parent
|
||||
parent = parent[SYMS.PARENT]
|
||||
delete old[SYMS.PARENT]
|
||||
delete old[MAJOR]
|
||||
}
|
||||
if (!again) {
|
||||
return val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Decoder.NOT_FOUND = NOT_FOUND
|
||||
module.exports = Decoder
|
||||
229
node_modules/cbor/lib/diagnose.js
generated
vendored
Normal file
229
node_modules/cbor/lib/diagnose.js
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
'use strict'
|
||||
|
||||
const stream = require('stream')
|
||||
const util = require('util')
|
||||
const Decoder = require('./decoder')
|
||||
const Simple = require('./simple')
|
||||
const utils = require('./utils')
|
||||
const constants = require('./constants')
|
||||
const bignumber = require('bignumber.js').BigNumber
|
||||
const NoFilter = require('nofilter')
|
||||
|
||||
const MT = constants.MT
|
||||
const SYMS = constants.SYMS
|
||||
|
||||
/**
|
||||
* Output the diagnostic format from a stream of CBOR bytes.
|
||||
*
|
||||
* @extends {stream.Transform}
|
||||
*/
|
||||
class Diagnose extends stream.Transform {
|
||||
|
||||
/**
|
||||
* Creates an instance of Diagnose.
|
||||
*
|
||||
* @param {Object} [options={}] - options for creation
|
||||
* @param {string} [options.separator='\n'] - output between detected objects
|
||||
* @param {boolean} [options.stream_errors=false] - put error info into the
|
||||
* output stream
|
||||
* @param {number} [options.max_depth=-1] - -1 for "until you run out of
|
||||
* memory". Set this to a finite positive number for un-trusted inputs.
|
||||
* Most standard inputs won't nest more than 100 or so levels; I've tested
|
||||
* into the millions before running out of memory.
|
||||
*/
|
||||
constructor(options) {
|
||||
const opts = Object.assign({
|
||||
separator: '\n',
|
||||
stream_errors: false
|
||||
}, options, {
|
||||
readableObjectMode: false,
|
||||
writableObjectMode: false
|
||||
})
|
||||
const separator = opts.separator
|
||||
delete opts.separator
|
||||
const stream_errors = opts.stream_errors
|
||||
delete opts.stream_errors
|
||||
super(opts)
|
||||
|
||||
this.float_bytes = -1
|
||||
this.separator = separator
|
||||
this.stream_errors = stream_errors
|
||||
this.parser = new Decoder(opts)
|
||||
this.parser.on('more-bytes', this._on_more.bind(this))
|
||||
this.parser.on('value', this._on_value.bind(this))
|
||||
this.parser.on('start', this._on_start.bind(this))
|
||||
this.parser.on('stop', this._on_stop.bind(this))
|
||||
this.parser.on('data', this._on_data.bind(this))
|
||||
this.parser.on('error', this._on_error.bind(this))
|
||||
}
|
||||
|
||||
_transform(fresh, encoding, cb) {
|
||||
return this.parser.write(fresh, encoding, cb)
|
||||
}
|
||||
|
||||
_flush(cb) {
|
||||
return this.parser._flush((er) => {
|
||||
if (this.stream_errors) {
|
||||
if (er) {
|
||||
this._on_error(er)
|
||||
}
|
||||
return cb()
|
||||
} else {
|
||||
return cb(er)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to return a string in diagnostic format.
|
||||
*
|
||||
* @param {(Buffer|string)} input - the CBOR bytes to format
|
||||
* @param {string} [encoding='hex'] - the encoding of input, ignored if
|
||||
* input is Buffer
|
||||
* @param {function(Error, string): undefined} cb - callback
|
||||
* @returns {Promise} if callback not specified
|
||||
*/
|
||||
static diagnose(input, encoding, cb) {
|
||||
if (input == null) {
|
||||
throw new Error('input required')
|
||||
}
|
||||
let opts = {}
|
||||
let encod = 'hex'
|
||||
switch (typeof encoding) {
|
||||
case 'function':
|
||||
cb = encoding
|
||||
encod = utils.guessEncoding(input)
|
||||
break
|
||||
case 'object':
|
||||
opts = utils.extend({}, encoding)
|
||||
encod = (opts.encoding != null) ?
|
||||
opts.encoding : utils.guessEncoding(input)
|
||||
delete opts.encoding
|
||||
break
|
||||
default:
|
||||
encod = (encoding != null) ? encoding : 'hex'
|
||||
}
|
||||
const bs = new NoFilter()
|
||||
const d = new Diagnose(opts)
|
||||
let p = null
|
||||
if (typeof cb === 'function') {
|
||||
d.on('end', () => cb(null, bs.toString('utf8')))
|
||||
d.on('error', cb)
|
||||
} else {
|
||||
p = new Promise((resolve, reject) => {
|
||||
d.on('end', () => resolve(bs.toString('utf8')))
|
||||
return d.on('error', reject)
|
||||
})
|
||||
}
|
||||
d.pipe(bs)
|
||||
d.end(input, encod)
|
||||
return p
|
||||
}
|
||||
|
||||
_on_error(er) {
|
||||
if (this.stream_errors) {
|
||||
return this.push(er.toString())
|
||||
} else {
|
||||
return this.emit('error', er)
|
||||
}
|
||||
}
|
||||
|
||||
_on_more(mt, len, parent_mt, pos) {
|
||||
if (mt === MT.SIMPLE_FLOAT) {
|
||||
return this.float_bytes = {
|
||||
2: 1,
|
||||
4: 2,
|
||||
8: 3
|
||||
}[len]
|
||||
}
|
||||
}
|
||||
|
||||
_fore(parent_mt, pos) {
|
||||
switch (parent_mt) {
|
||||
case MT.BYTE_STRING:
|
||||
case MT.UTF8_STRING:
|
||||
case MT.ARRAY:
|
||||
if (pos > 0) {
|
||||
return this.push(', ')
|
||||
}
|
||||
break
|
||||
case MT.MAP:
|
||||
if (pos > 0) {
|
||||
if (pos % 2) {
|
||||
return this.push(': ')
|
||||
} else {
|
||||
return this.push(', ')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_on_value(val, parent_mt, pos) {
|
||||
if (val === SYMS.BREAK) {
|
||||
return
|
||||
}
|
||||
this._fore(parent_mt, pos)
|
||||
return this.push((() => {
|
||||
switch (false) {
|
||||
case val !== SYMS.NULL:
|
||||
return 'null'
|
||||
case val !== SYMS.UNDEFINED:
|
||||
return 'undefined'
|
||||
case typeof val !== 'string':
|
||||
return JSON.stringify(val)
|
||||
case !(this.float_bytes > 0):
|
||||
const fb = this.float_bytes
|
||||
this.float_bytes = -1
|
||||
return (util.inspect(val)) + '_' + fb
|
||||
case !Buffer.isBuffer(val):
|
||||
return 'h\'' + (val.toString('hex')) + '\''
|
||||
case !(val instanceof bignumber):
|
||||
return val.toString()
|
||||
default:
|
||||
return util.inspect(val)
|
||||
}
|
||||
})())
|
||||
}
|
||||
|
||||
_on_start(mt, tag, parent_mt, pos) {
|
||||
this._fore(parent_mt, pos)
|
||||
switch (mt) {
|
||||
case MT.TAG:
|
||||
this.push(`${tag}(`)
|
||||
break
|
||||
case MT.ARRAY:
|
||||
this.push('[')
|
||||
break
|
||||
case MT.MAP:
|
||||
this.push('{')
|
||||
break
|
||||
case MT.BYTE_STRING:
|
||||
case MT.UTF8_STRING:
|
||||
this.push('(')
|
||||
break
|
||||
}
|
||||
if (tag === SYMS.STREAM) {
|
||||
return this.push('_ ')
|
||||
}
|
||||
}
|
||||
|
||||
_on_stop(mt) {
|
||||
switch (mt) {
|
||||
case MT.TAG:
|
||||
return this.push(')')
|
||||
case MT.ARRAY:
|
||||
return this.push(']')
|
||||
case MT.MAP:
|
||||
return this.push('}')
|
||||
case MT.BYTE_STRING:
|
||||
case MT.UTF8_STRING:
|
||||
return this.push(')')
|
||||
}
|
||||
}
|
||||
|
||||
_on_data() {
|
||||
return this.push(this.separator)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Diagnose
|
||||
738
node_modules/cbor/lib/encoder.js
generated
vendored
Normal file
738
node_modules/cbor/lib/encoder.js
generated
vendored
Normal file
@@ -0,0 +1,738 @@
|
||||
'use strict'
|
||||
|
||||
const stream = require('stream')
|
||||
const url = require('url')
|
||||
const bignumber = require('bignumber.js').BigNumber
|
||||
const NoFilter = require('nofilter')
|
||||
const Tagged = require('./tagged')
|
||||
const Simple = require('./simple')
|
||||
const utils = require('./utils')
|
||||
|
||||
const constants = require('./constants')
|
||||
const MT = constants.MT
|
||||
const NUMBYTES = constants.NUMBYTES
|
||||
const SHIFT32 = constants.SHIFT32
|
||||
const SYMS = constants.SYMS
|
||||
const TAG = constants.TAG
|
||||
const HALF = (constants.MT.SIMPLE_FLOAT << 5) | constants.NUMBYTES.TWO
|
||||
const FLOAT = (constants.MT.SIMPLE_FLOAT << 5) | constants.NUMBYTES.FOUR
|
||||
const DOUBLE = (constants.MT.SIMPLE_FLOAT << 5) | constants.NUMBYTES.EIGHT
|
||||
const TRUE = (constants.MT.SIMPLE_FLOAT << 5) | constants.SIMPLE.TRUE
|
||||
const FALSE = (constants.MT.SIMPLE_FLOAT << 5) | constants.SIMPLE.FALSE
|
||||
const UNDEFINED = (constants.MT.SIMPLE_FLOAT << 5) | constants.SIMPLE.UNDEFINED
|
||||
const NULL = (constants.MT.SIMPLE_FLOAT << 5) | constants.SIMPLE.NULL
|
||||
|
||||
const BI = utils.bigIntize(constants.BI)
|
||||
const BN = constants.BN
|
||||
const BUF_NAN = Buffer.from('f97e00', 'hex')
|
||||
const BUF_INF_NEG = Buffer.from('f9fc00', 'hex')
|
||||
const BUF_INF_POS = Buffer.from('f97c00', 'hex')
|
||||
const BUF_NEG_ZERO = Buffer.from('f98000', 'hex')
|
||||
const LOOP_DETECT = Symbol('CBOR_LOOP_DETECT')
|
||||
|
||||
/**
|
||||
* Transform JavaScript values into CBOR bytes. The `Writable` side of
|
||||
* the stream is in object mode.
|
||||
*
|
||||
* @extends {stream.Transform}
|
||||
*/
|
||||
class Encoder extends stream.Transform {
|
||||
|
||||
/**
|
||||
* Creates an instance of Encoder.
|
||||
*
|
||||
* @param {Object} [options={}] - options for the encoder
|
||||
* @param {any[]} [options.genTypes=[]] - array of pairs of `type`,
|
||||
* `function(Encoder)` for semantic types to be encoded. Not needed
|
||||
* for Array, Date, Buffer, Map, RegExp, Set, Url, or bignumber.
|
||||
* @param {boolean} [options.canonical=false] - should the output be
|
||||
* canonicalized
|
||||
* @param {boolean|Symbol} [options.detectLoops=false] - should object loops
|
||||
* be detected? This will currently modify the encoded object graph
|
||||
* by adding a Symbol property to each object. If this bothers you,
|
||||
* call `removeLoopDetectors` on the encoded object when done. Do not
|
||||
* encode the same object twice on the same encoder, without calling
|
||||
* `removeLoopDetectors` in between.
|
||||
* @param {("number"|"float"|"int"|"string")} [options.dateType="number"] -
|
||||
* how should dates be encoded? "number" means float or int, if no
|
||||
* fractional seconds.
|
||||
* @param {any} [options.encodeUndefined=undefined] - How should an
|
||||
* "undefined" in the input be encoded. By default, just encode a CBOR
|
||||
* undefined. If this is a buffer, use those bytes without re-encoding
|
||||
* them. If this is a function, the function will be called (which is
|
||||
* a good time to throw an exception, if that's what you want), and the
|
||||
* return value will be used according to these rules. Anything
|
||||
* else will be encoded as CBOR.
|
||||
* @param {boolean} [options.disallowUndefinedKeys=false] - Should "undefined"
|
||||
* be disallowed as a key in a Map that is serialized? If this is true,
|
||||
* encode(new Map([[undefined, 1]])) will throw an exception. Note that
|
||||
* it is impossible to get a key of undefined in a normal JS object.
|
||||
* @param {boolean} [options.collapseBigIntegers=false] - Should integers
|
||||
* that come in as BigNumber integers and ECMAscript bigint's be encoded
|
||||
* as normal CBOR integers if they fit, discarding type information?
|
||||
*/
|
||||
constructor(options) {
|
||||
const opts = Object.assign({}, options, {
|
||||
readableObjectMode: false,
|
||||
writableObjectMode: true
|
||||
})
|
||||
super(opts)
|
||||
|
||||
this.canonical = opts.canonical
|
||||
this.encodeUndefined = opts.encodeUndefined
|
||||
this.disallowUndefinedKeys = !!opts.disallowUndefinedKeys
|
||||
this.dateType = (opts.dateType != null) ?
|
||||
opts.dateType.toLowerCase() : 'number'
|
||||
this.collapseBigIntegers = !!opts.collapseBigIntegers
|
||||
|
||||
// new Symbol for each instance. Note: means we can't re-use the same
|
||||
// encoder and encoded object
|
||||
if (typeof(opts.detectLoops) === 'symbol') {
|
||||
this.detectLoops = opts.detectLoops
|
||||
} else {
|
||||
this.detectLoops = !!opts.detectLoops ? Symbol('CBOR_DETECT') : null
|
||||
}
|
||||
|
||||
this.semanticTypes = [
|
||||
Array, this._pushArray,
|
||||
Date, this._pushDate,
|
||||
Buffer, this._pushBuffer,
|
||||
Map, this._pushMap,
|
||||
NoFilter, this._pushNoFilter,
|
||||
RegExp, this._pushRegexp,
|
||||
Set, this._pushSet,
|
||||
bignumber, this._pushBigNumber,
|
||||
ArrayBuffer, this._pushUint8Array,
|
||||
Uint8ClampedArray, this._pushUint8Array,
|
||||
Uint8Array, this._pushUint8Array,
|
||||
Uint16Array, this._pushArray,
|
||||
Uint32Array, this._pushArray,
|
||||
Int8Array, this._pushArray,
|
||||
Int16Array, this._pushArray,
|
||||
Int32Array, this._pushArray,
|
||||
Float32Array, this._pushFloat32Array,
|
||||
Float64Array, this._pushFloat64Array
|
||||
]
|
||||
|
||||
// tsc doesn't know about old Url
|
||||
if (url['Url']) {
|
||||
this.semanticTypes.push(url['Url'], this._pushUrl)
|
||||
}
|
||||
if (url['URL']) {
|
||||
this.semanticTypes.push(url['URL'], this._pushURL)
|
||||
}
|
||||
|
||||
const addTypes = opts.genTypes || []
|
||||
for (let i = 0, len = addTypes.length; i < len; i += 2) {
|
||||
this.addSemanticType(addTypes[i], addTypes[i + 1])
|
||||
}
|
||||
}
|
||||
|
||||
_transform(fresh, encoding, cb) {
|
||||
const ret = this.pushAny(fresh)
|
||||
// Old transformers might not return bool. undefined !== false
|
||||
return cb((ret === false) ? new Error('Push Error') : undefined)
|
||||
}
|
||||
|
||||
_flush(cb) {
|
||||
return cb()
|
||||
}
|
||||
|
||||
/**
|
||||
* @callback encodeFunction
|
||||
* @param {Encoder} encoder - the encoder to serialize into. Call "write"
|
||||
* on the encoder as needed.
|
||||
* @return {bool} - true on success, else false
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add an encoding function to the list of supported semantic types. This is
|
||||
* useful for objects for which you can't add an encodeCBOR method
|
||||
*
|
||||
* @param {any} type
|
||||
* @param {any} fun
|
||||
* @returns {encodeFunction}
|
||||
*/
|
||||
addSemanticType(type, fun) {
|
||||
for (let i = 0, len = this.semanticTypes.length; i < len; i += 2) {
|
||||
const typ = this.semanticTypes[i]
|
||||
if (typ === type) {
|
||||
const old = this.semanticTypes[i + 1]
|
||||
this.semanticTypes[i + 1] = fun
|
||||
return old
|
||||
}
|
||||
}
|
||||
this.semanticTypes.push(type, fun)
|
||||
return null
|
||||
}
|
||||
|
||||
_pushUInt8(val) {
|
||||
const b = Buffer.allocUnsafe(1)
|
||||
b.writeUInt8(val, 0)
|
||||
return this.push(b)
|
||||
}
|
||||
|
||||
_pushUInt16BE(val) {
|
||||
const b = Buffer.allocUnsafe(2)
|
||||
b.writeUInt16BE(val, 0)
|
||||
return this.push(b)
|
||||
}
|
||||
|
||||
_pushUInt32BE(val) {
|
||||
const b = Buffer.allocUnsafe(4)
|
||||
b.writeUInt32BE(val, 0)
|
||||
return this.push(b)
|
||||
}
|
||||
|
||||
_pushFloatBE(val) {
|
||||
const b = Buffer.allocUnsafe(4)
|
||||
b.writeFloatBE(val, 0)
|
||||
return this.push(b)
|
||||
}
|
||||
|
||||
_pushDoubleBE(val) {
|
||||
const b = Buffer.allocUnsafe(8)
|
||||
b.writeDoubleBE(val, 0)
|
||||
return this.push(b)
|
||||
}
|
||||
|
||||
_pushNaN() {
|
||||
return this.push(BUF_NAN)
|
||||
}
|
||||
|
||||
_pushInfinity(obj) {
|
||||
const half = (obj < 0) ? BUF_INF_NEG : BUF_INF_POS
|
||||
return this.push(half)
|
||||
}
|
||||
|
||||
_pushFloat(obj) {
|
||||
if (this.canonical) {
|
||||
// TODO: is this enough slower to hide behind canonical?
|
||||
// It's certainly enough of a hack (see utils.parseHalf)
|
||||
|
||||
// From section 3.9:
|
||||
// If a protocol allows for IEEE floats, then additional canonicalization
|
||||
// rules might need to be added. One example rule might be to have all
|
||||
// floats start as a 64-bit float, then do a test conversion to a 32-bit
|
||||
// float; if the result is the same numeric value, use the shorter value
|
||||
// and repeat the process with a test conversion to a 16-bit float. (This
|
||||
// rule selects 16-bit float for positive and negative Infinity as well.)
|
||||
|
||||
// which seems pretty much backwards to me.
|
||||
const b2 = Buffer.allocUnsafe(2)
|
||||
if (utils.writeHalf(b2, obj)) {
|
||||
if (utils.parseHalf(b2) === obj) {
|
||||
return this._pushUInt8(HALF) && this.push(b2)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Math.fround(obj) === obj) {
|
||||
return this._pushUInt8(FLOAT) && this._pushFloatBE(obj)
|
||||
}
|
||||
|
||||
return this._pushUInt8(DOUBLE) && this._pushDoubleBE(obj)
|
||||
}
|
||||
|
||||
_pushInt(obj, mt, orig) {
|
||||
const m = mt << 5
|
||||
switch (false) {
|
||||
case !(obj < 24):
|
||||
return this._pushUInt8(m | obj)
|
||||
case !(obj <= 0xff):
|
||||
return this._pushUInt8(m | NUMBYTES.ONE) && this._pushUInt8(obj)
|
||||
case !(obj <= 0xffff):
|
||||
return this._pushUInt8(m | NUMBYTES.TWO) && this._pushUInt16BE(obj)
|
||||
case !(obj <= 0xffffffff):
|
||||
return this._pushUInt8(m | NUMBYTES.FOUR) && this._pushUInt32BE(obj)
|
||||
case !(obj <= Number.MAX_SAFE_INTEGER):
|
||||
return this._pushUInt8(m | NUMBYTES.EIGHT) &&
|
||||
this._pushUInt32BE(Math.floor(obj / SHIFT32)) &&
|
||||
this._pushUInt32BE(obj % SHIFT32)
|
||||
default:
|
||||
if (mt === MT.NEG_INT) {
|
||||
return this._pushFloat(orig)
|
||||
} else {
|
||||
return this._pushFloat(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_pushIntNum(obj) {
|
||||
if (Object.is(obj, -0)) {
|
||||
return this.push(BUF_NEG_ZERO)
|
||||
}
|
||||
|
||||
if (obj < 0) {
|
||||
return this._pushInt(-obj - 1, MT.NEG_INT, obj)
|
||||
} else {
|
||||
return this._pushInt(obj, MT.POS_INT)
|
||||
}
|
||||
}
|
||||
|
||||
_pushNumber(obj) {
|
||||
switch (false) {
|
||||
case !isNaN(obj):
|
||||
return this._pushNaN()
|
||||
case isFinite(obj):
|
||||
return this._pushInfinity(obj)
|
||||
case Math.round(obj) !== obj:
|
||||
return this._pushIntNum(obj)
|
||||
default:
|
||||
return this._pushFloat(obj)
|
||||
}
|
||||
}
|
||||
|
||||
_pushString(obj) {
|
||||
const len = Buffer.byteLength(obj, 'utf8')
|
||||
return this._pushInt(len, MT.UTF8_STRING) && this.push(obj, 'utf8')
|
||||
}
|
||||
|
||||
_pushBoolean(obj) {
|
||||
return this._pushUInt8(obj ? TRUE : FALSE)
|
||||
}
|
||||
|
||||
_pushUndefined(obj) {
|
||||
switch (typeof this.encodeUndefined) {
|
||||
case 'undefined':
|
||||
return this._pushUInt8(UNDEFINED)
|
||||
case 'function':
|
||||
return this.pushAny(this.encodeUndefined.call(this, obj))
|
||||
case 'object':
|
||||
if (Buffer.isBuffer(this.encodeUndefined)) {
|
||||
return this.push(this.encodeUndefined)
|
||||
}
|
||||
}
|
||||
return this.pushAny(this.encodeUndefined)
|
||||
}
|
||||
|
||||
_pushNull(obj) {
|
||||
return this._pushUInt8(NULL)
|
||||
}
|
||||
|
||||
_pushArray(gen, obj) {
|
||||
const len = obj.length
|
||||
if (!gen._pushInt(len, MT.ARRAY)) {
|
||||
return false
|
||||
}
|
||||
for (let j = 0; j < len; j++) {
|
||||
if (!gen.pushAny(obj[j])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
_pushTag(tag) {
|
||||
return this._pushInt(tag, MT.TAG)
|
||||
}
|
||||
|
||||
_pushDate(gen, obj) {
|
||||
switch (gen.dateType) {
|
||||
case 'string':
|
||||
return gen._pushTag(TAG.DATE_STRING) &&
|
||||
gen._pushString(obj.toISOString())
|
||||
case 'int':
|
||||
case 'integer':
|
||||
return gen._pushTag(TAG.DATE_EPOCH) &&
|
||||
gen._pushIntNum(Math.round(obj / 1000))
|
||||
case 'float':
|
||||
// force float
|
||||
return gen._pushTag(TAG.DATE_EPOCH) &&
|
||||
gen._pushFloat(obj / 1000)
|
||||
case 'number':
|
||||
default:
|
||||
// if we happen to have an integral number of seconds,
|
||||
// use integer. Otherwise, use float.
|
||||
return gen._pushTag(TAG.DATE_EPOCH) &&
|
||||
gen.pushAny(obj / 1000)
|
||||
}
|
||||
}
|
||||
|
||||
_pushBuffer(gen, obj) {
|
||||
return gen._pushInt(obj.length, MT.BYTE_STRING) && gen.push(obj)
|
||||
}
|
||||
|
||||
_pushNoFilter(gen, obj) {
|
||||
return gen._pushBuffer(gen, obj.slice())
|
||||
}
|
||||
|
||||
_pushRegexp(gen, obj) {
|
||||
return gen._pushTag(TAG.REGEXP) && gen.pushAny(obj.source)
|
||||
}
|
||||
|
||||
_pushSet(gen, obj) {
|
||||
if (!gen._pushInt(obj.size, MT.ARRAY)) {
|
||||
return false
|
||||
}
|
||||
for (const x of obj) {
|
||||
if (!gen.pushAny(x)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
_pushUrl(gen, obj) {
|
||||
return gen._pushTag(TAG.URI) && gen.pushAny(obj.format())
|
||||
}
|
||||
|
||||
_pushURL(gen, obj) {
|
||||
return gen._pushTag(TAG.URI) && gen.pushAny(obj.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {bignumber} obj
|
||||
* @private
|
||||
*/
|
||||
_pushBigint(obj) {
|
||||
let m = MT.POS_INT
|
||||
let tag = TAG.POS_BIGINT
|
||||
|
||||
if (obj.isNegative()) {
|
||||
obj = obj.negated().minus(1)
|
||||
m = MT.NEG_INT
|
||||
tag = TAG.NEG_BIGINT
|
||||
}
|
||||
|
||||
if (this.collapseBigIntegers &&
|
||||
obj.lte(BN.MAXINT64)) {
|
||||
// special handiling for 64bits
|
||||
if (obj.lte(BN.MAXINT32)) {
|
||||
return this._pushInt(obj.toNumber(), m)
|
||||
}
|
||||
return this._pushUInt8((m << 5) | NUMBYTES.EIGHT) &&
|
||||
this._pushUInt32BE(obj.dividedToIntegerBy(BN.SHIFT32).toNumber()) &&
|
||||
this._pushUInt32BE(obj.mod(BN.SHIFT32).toNumber())
|
||||
}
|
||||
let str = obj.toString(16)
|
||||
if (str.length % 2) {
|
||||
str = '0' + str
|
||||
}
|
||||
const buf = Buffer.from(str, 'hex')
|
||||
return this._pushTag(tag) && this._pushBuffer(this, buf)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {bigint} obj
|
||||
* @private
|
||||
*/
|
||||
_pushJSBigint(obj) {
|
||||
let m = MT.POS_INT
|
||||
let tag = TAG.POS_BIGINT
|
||||
// BigInt doesn't have -0
|
||||
if (obj < 0) {
|
||||
obj = -obj + BI.MINUS_ONE
|
||||
m = MT.NEG_INT
|
||||
tag = TAG.NEG_BIGINT
|
||||
}
|
||||
|
||||
if (this.collapseBigIntegers &&
|
||||
(obj <= BI.MAXINT64)) {
|
||||
// special handiling for 64bits
|
||||
if (obj <= 0xffffffff) {
|
||||
return this._pushInt(Number(obj), m)
|
||||
}
|
||||
return this._pushUInt8((m << 5) | NUMBYTES.EIGHT) &&
|
||||
this._pushUInt32BE(Number(obj / BI.SHIFT32)) &&
|
||||
this._pushUInt32BE(Number(obj % BI.SHIFT32))
|
||||
}
|
||||
|
||||
let str = obj.toString(16)
|
||||
if (str.length % 2) {
|
||||
str = '0' + str
|
||||
}
|
||||
const buf = Buffer.from(str, 'hex')
|
||||
return this._pushTag(tag) && this._pushBuffer(this, buf)
|
||||
}
|
||||
|
||||
_pushBigNumber(gen, obj) {
|
||||
if (obj.isNaN()) {
|
||||
return gen._pushNaN()
|
||||
}
|
||||
if (!obj.isFinite()) {
|
||||
return gen._pushInfinity(obj.isNegative() ? -Infinity : Infinity)
|
||||
}
|
||||
if (obj.isInteger()) {
|
||||
return gen._pushBigint(obj)
|
||||
}
|
||||
if (!(gen._pushTag(TAG.DECIMAL_FRAC) &&
|
||||
gen._pushInt(2, MT.ARRAY))) {
|
||||
return false
|
||||
}
|
||||
|
||||
const dec = obj.decimalPlaces()
|
||||
const slide = obj.times(new bignumber(10).pow(dec))
|
||||
if (!gen._pushIntNum(-dec)) {
|
||||
return false
|
||||
}
|
||||
if (slide.abs().isLessThan(BN.MAXINT)) {
|
||||
return gen._pushIntNum(slide.toNumber())
|
||||
} else {
|
||||
return gen._pushBigint(slide)
|
||||
}
|
||||
}
|
||||
|
||||
_pushMap(gen, obj) {
|
||||
if (!gen._pushInt(obj.size, MT.MAP)) {
|
||||
return false
|
||||
}
|
||||
// memoizing the cbor only helps in certain cases, and hurts in most
|
||||
// others. Just avoid it.
|
||||
if (gen.canonical) {
|
||||
// keep the key/value pairs together, so we don't have to do odd
|
||||
// gets with object keys later
|
||||
const entries = [...obj.entries()]
|
||||
const enc = new Encoder(this) // TODO: fix genTypes
|
||||
const bs = new NoFilter({highWaterMark:this.readableHighWaterMark})
|
||||
enc.pipe(bs)
|
||||
entries.sort(([a], [b]) => {
|
||||
// a, b are the keys
|
||||
enc.pushAny(a)
|
||||
const a_cbor = bs.read()
|
||||
enc.pushAny(b)
|
||||
const b_cbor = bs.read()
|
||||
return a_cbor.compare(b_cbor)
|
||||
})
|
||||
for (const [k, v] of entries) {
|
||||
if (gen.disallowUndefinedKeys && (typeof k === 'undefined')) {
|
||||
throw new Error('Invalid Map key: undefined')
|
||||
}
|
||||
if (!(gen.pushAny(k) && gen.pushAny(v))) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const [k, v] of obj) {
|
||||
if (gen.disallowUndefinedKeys && (typeof k === 'undefined')) {
|
||||
throw new Error('Invalid Map key: undefined')
|
||||
}
|
||||
if (!(gen.pushAny(k) && gen.pushAny(v))) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
_pushUint8Array(gen, obj) {
|
||||
return gen._pushBuffer(gen, Buffer.from(obj))
|
||||
}
|
||||
|
||||
_pushFloat32Array(gen, obj) {
|
||||
const len = obj.length
|
||||
if (!gen._pushInt(len, MT.ARRAY)) {
|
||||
return false
|
||||
}
|
||||
for (let j = 0; j < len; j++) {
|
||||
if (!gen._pushUInt8(FLOAT) || !gen._pushFloatBE(obj[j])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
_pushFloat64Array(gen, obj) {
|
||||
const len = obj.length
|
||||
if (!gen._pushInt(len, MT.ARRAY)) {
|
||||
return false
|
||||
}
|
||||
for (let j = 0; j < len; j++) {
|
||||
if (!gen._pushUInt8(DOUBLE) || !gen._pushDoubleBE(obj[j])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
removeLoopDetectors(obj) {
|
||||
if (!this.detectLoops || (typeof(obj) !== 'object') || !obj) {
|
||||
return false
|
||||
}
|
||||
const dl = obj[LOOP_DETECT]
|
||||
if (!dl || (dl !== this.detectLoops)) {
|
||||
// ironically, use loop marking to detect loops on removal as well
|
||||
return false
|
||||
}
|
||||
delete obj[LOOP_DETECT]
|
||||
if (Array.isArray(obj)) {
|
||||
for (const i of obj) {
|
||||
this.removeLoopDetectors(i)
|
||||
}
|
||||
} else {
|
||||
for (const k in obj) {
|
||||
this.removeLoopDetectors(obj[k])
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
_pushObject(obj) {
|
||||
if (!obj) {
|
||||
return this._pushNull(obj)
|
||||
}
|
||||
if (this.detectLoops) {
|
||||
if (obj[LOOP_DETECT] === this.detectLoops) {
|
||||
throw new Error('Loop detected while CBOR encoding')
|
||||
} else {
|
||||
obj[LOOP_DETECT] = this.detectLoops
|
||||
}
|
||||
}
|
||||
const f = obj.encodeCBOR
|
||||
if (typeof f === 'function') {
|
||||
return f.call(obj, this)
|
||||
}
|
||||
for (let i = 0, len1 = this.semanticTypes.length; i < len1; i += 2) {
|
||||
const typ = this.semanticTypes[i]
|
||||
if (obj instanceof typ) {
|
||||
return this.semanticTypes[i + 1].call(obj, this, obj)
|
||||
}
|
||||
}
|
||||
const keys = Object.keys(obj)
|
||||
const cbor_keys = {}
|
||||
if (this.canonical) {
|
||||
// note: this can't be a normal sort, because 'b' needs to sort before
|
||||
// 'aa'
|
||||
keys.sort((a, b) => {
|
||||
// Always strings, so don't bother to pass options.
|
||||
// hold on to the cbor versions, since there's no need
|
||||
// to encode more than once
|
||||
const a_cbor = cbor_keys[a] || (cbor_keys[a] = Encoder.encode(a))
|
||||
const b_cbor = cbor_keys[b] || (cbor_keys[b] = Encoder.encode(b))
|
||||
|
||||
return a_cbor.compare(b_cbor)
|
||||
})
|
||||
}
|
||||
if (!this._pushInt(keys.length, MT.MAP)) {
|
||||
return false
|
||||
}
|
||||
let ck
|
||||
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
||||
const k = keys[j]
|
||||
if (this.canonical && ((ck = cbor_keys[k]))) {
|
||||
if (!this.push(ck)) { // already a Buffer
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if (!this._pushString(k)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (!this.pushAny(obj[k])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Push any supported type onto the encoded stream
|
||||
*
|
||||
* @param {any} obj
|
||||
* @returns {boolean} true on success
|
||||
*/
|
||||
pushAny(obj) {
|
||||
switch (typeof obj) {
|
||||
case 'number':
|
||||
return this._pushNumber(obj)
|
||||
case 'bigint':
|
||||
return this._pushJSBigint(obj)
|
||||
case 'string':
|
||||
return this._pushString(obj)
|
||||
case 'boolean':
|
||||
return this._pushBoolean(obj)
|
||||
case 'undefined':
|
||||
return this._pushUndefined(obj)
|
||||
case 'object':
|
||||
return this._pushObject(obj)
|
||||
case 'symbol':
|
||||
switch (obj) {
|
||||
case SYMS.NULL:
|
||||
return this._pushNull(null)
|
||||
case SYMS.UNDEFINED:
|
||||
return this._pushUndefined(void 0)
|
||||
// TODO: Add pluggable support for other symbols
|
||||
default:
|
||||
throw new Error('Unknown symbol: ' + obj.toString())
|
||||
}
|
||||
default:
|
||||
throw new Error(
|
||||
'Unknown type: ' + typeof obj + ', ' +
|
||||
(!!obj ? obj.toString() : ''))
|
||||
}
|
||||
}
|
||||
|
||||
/* backwards-compat wrapper */
|
||||
_pushAny(obj) {
|
||||
// TODO: write deprecation warning
|
||||
return this.pushAny(obj)
|
||||
}
|
||||
|
||||
_encodeAll(objs) {
|
||||
const bs = new NoFilter({ highWaterMark:this.readableHighWaterMark })
|
||||
this.pipe(bs)
|
||||
for (const o of objs) {
|
||||
this.pushAny(o)
|
||||
}
|
||||
this.end()
|
||||
return bs.read()
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode one or more JavaScript objects, and return a Buffer containing the
|
||||
* CBOR bytes.
|
||||
*
|
||||
* @param {...any} objs - the objects to encode
|
||||
* @returns {Buffer} - the encoded objects
|
||||
*/
|
||||
static encode(...objs) {
|
||||
return new Encoder()._encodeAll(objs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode one or more JavaScript objects canonically (slower!), and return
|
||||
* a Buffer containing the CBOR bytes.
|
||||
*
|
||||
* @param {...any} objs - the objects to encode
|
||||
* @returns {Buffer} - the encoded objects
|
||||
*/
|
||||
static encodeCanonical(...objs) {
|
||||
return new Encoder({canonical: true})._encodeAll(objs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode one JavaScript object using the given options.
|
||||
*
|
||||
* @static
|
||||
* @param {any} obj - the object to encode
|
||||
* @param {Object?} options - passed to the Encoder constructor
|
||||
* @returns {Buffer} - the encoded objects
|
||||
*/
|
||||
static encodeOne(obj, options) {
|
||||
return new Encoder(options)._encodeAll([obj])
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode one JavaScript object using the given options in a way that
|
||||
* is more resilient to objects being larger than the highWaterMark
|
||||
* number of bytes. As with the other static encode functions, this
|
||||
* will still use a large amount of memory. Use a stream-based approach
|
||||
* directly if you need to process large and complicated inputs.
|
||||
*
|
||||
* @param {any} obj - the object to encode
|
||||
* @param {Object?} options - passed to the Encoder constructor
|
||||
*/
|
||||
static encodeAsync(obj, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const bufs = []
|
||||
const enc = new Encoder(options)
|
||||
enc.on('data', buf => bufs.push(buf))
|
||||
enc.on('error', reject)
|
||||
enc.on('finish', () => resolve(Buffer.concat(bufs)))
|
||||
enc.pushAny(obj)
|
||||
enc.end()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Encoder
|
||||
176
node_modules/cbor/lib/map.js
generated
vendored
Normal file
176
node_modules/cbor/lib/map.js
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
'use strict'
|
||||
|
||||
const encoder = require('./encoder')
|
||||
const decoder = require('./decoder')
|
||||
const constants = require('./constants')
|
||||
const MT = constants.MT
|
||||
|
||||
/**
|
||||
* Wrapper around a JavaScript Map object that allows the keys to be
|
||||
* any complex type. The base Map object allows this, but will only
|
||||
* compare the keys by identity, not by value. CborMap translates keys
|
||||
* to CBOR first (and base64's them to ensure by-value comparison).
|
||||
*
|
||||
* This is not a subclass of Object, because it would be tough to get
|
||||
* the semantics to be an exact match.
|
||||
*
|
||||
* @class CborMap
|
||||
* @extends {Map}
|
||||
*/
|
||||
class CborMap extends Map {
|
||||
/**
|
||||
* Creates an instance of CborMap.
|
||||
* @param {Iterable<any, any>} [iterable] An Array or other iterable
|
||||
* object whose elements are key-value pairs (arrays with two elements, e.g.
|
||||
* <code>[[ 1, 'one' ],[ 2, 'two' ]]</code>). Each key-value pair is added
|
||||
* to the new CborMap; null values are treated as undefined.
|
||||
*/
|
||||
constructor(iterable) {
|
||||
super(iterable)
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
static _encode(key) {
|
||||
return encoder.encodeCanonical(key).toString('base64')
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
static _decode(key) {
|
||||
return decoder.decodeFirstSync(key, 'base64')
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a specified element.
|
||||
*
|
||||
* @param {any} key The key identifying the element to retrieve.
|
||||
* Can be any type, which will be serialized into CBOR and compared by
|
||||
* value.
|
||||
* @returns {any} The element if it exists, or <code>undefined</code>.
|
||||
*/
|
||||
get(key) {
|
||||
return super.get(CborMap._encode(key))
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or updates an element with a specified key and value.
|
||||
*
|
||||
* @param {any} key The key identifying the element to store.
|
||||
* Can be any type, which will be serialized into CBOR and compared by
|
||||
* value.
|
||||
* @param {any} val The element to store
|
||||
*/
|
||||
set(key, val) {
|
||||
return super.set(CborMap._encode(key), val)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified element.
|
||||
*
|
||||
* @param {any} key The key identifying the element to delete.
|
||||
* Can be any type, which will be serialized into CBOR and compared by
|
||||
* value.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
delete(key) {
|
||||
return super.delete(CborMap._encode(key))
|
||||
}
|
||||
|
||||
/**
|
||||
* Does an element with the specified key exist?
|
||||
*
|
||||
* @param {any} key The key identifying the element to check.
|
||||
* Can be any type, which will be serialized into CBOR and compared by
|
||||
* value.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
has(key) {
|
||||
return super.has(CborMap._encode(key))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Iterator object that contains the keys for each element
|
||||
* in the Map object in insertion order. The keys are decoded into their
|
||||
* original format.
|
||||
*
|
||||
* @returns {IterableIterator<any>}
|
||||
*/
|
||||
*keys() {
|
||||
for (const k of super.keys()) {
|
||||
yield CborMap._decode(k)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Iterator object that contains the [key, value] pairs for
|
||||
* each element in the Map object in insertion order.
|
||||
*
|
||||
* @returns {IterableIterator}
|
||||
*/
|
||||
*entries() {
|
||||
for (const kv of super.entries()) {
|
||||
yield [CborMap._decode(kv[0]), kv[1]]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Iterator object that contains the [key, value] pairs for
|
||||
* each element in the Map object in insertion order.
|
||||
*
|
||||
* @returns {IterableIterator}
|
||||
*/
|
||||
[Symbol.iterator]() {
|
||||
return this.entries()
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a provided function once per each key/value pair in the Map
|
||||
* object, in insertion order.
|
||||
*
|
||||
* @param {function(any, any, Map): undefined} fun Function to execute for
|
||||
* each element, which takes a value, a key, and the Map being traversed.
|
||||
* @param {any} thisArg Value to use as this when executing callback
|
||||
*/
|
||||
forEach(fun, thisArg) {
|
||||
if (typeof(fun) !== 'function') {
|
||||
throw new TypeError('Must be function')
|
||||
}
|
||||
for (const kv of super.entries()) {
|
||||
fun.call(this, kv[1], CborMap._decode(kv[0]), this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the simple value onto the CBOR stream
|
||||
*
|
||||
* @param {Object} gen The generator to push onto
|
||||
* @returns {boolean} true on success
|
||||
*/
|
||||
encodeCBOR(gen) {
|
||||
if (!gen._pushInt(this.size, MT.MAP)) {
|
||||
return false
|
||||
}
|
||||
if (gen.canonical) {
|
||||
const entries = Array.from(super.entries())
|
||||
.map((kv) => [Buffer.from(kv[0], 'base64'), kv[1]])
|
||||
entries.sort((a, b) => a[0].compare(b[0]))
|
||||
for (const kv of entries) {
|
||||
if (!(gen.push(kv[0]) && gen.pushAny(kv[1]))) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const kv of super.entries()) {
|
||||
if (!(gen.push(Buffer.from(kv[0], 'base64')) && gen.pushAny(kv[1]))) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CborMap
|
||||
115
node_modules/cbor/lib/simple.js
generated
vendored
Normal file
115
node_modules/cbor/lib/simple.js
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
'use strict'
|
||||
|
||||
const util = require('util')
|
||||
const constants = require('./constants')
|
||||
const MT = constants.MT
|
||||
const SIMPLE = constants.SIMPLE
|
||||
const SYMS = constants.SYMS
|
||||
|
||||
/**
|
||||
* A CBOR Simple Value that does not map onto a known constant.
|
||||
*/
|
||||
class Simple {
|
||||
/**
|
||||
* Creates an instance of Simple.
|
||||
*
|
||||
* @param {number} value - the simple value's integer value
|
||||
*/
|
||||
constructor(value) {
|
||||
if (typeof value !== 'number') {
|
||||
throw new Error('Invalid Simple type: ' + (typeof value))
|
||||
}
|
||||
if ((value < 0) || (value > 255) || ((value|0) !== value)) {
|
||||
throw new Error('value must be a small positive integer: ' + value)
|
||||
}
|
||||
this.value = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug string for simple value
|
||||
*
|
||||
* @returns {string} simple(value)
|
||||
*/
|
||||
toString() {
|
||||
return 'simple(' + this.value + ')'
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug string for simple value
|
||||
*
|
||||
* @returns {string} simple(value)
|
||||
*/
|
||||
[util.inspect.custom](depth, opts) {
|
||||
return 'simple(' + this.value + ')'
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug string for simple value (backward-compatibility version)
|
||||
*
|
||||
* @returns {string} simple(value)
|
||||
*/
|
||||
inspect(depth, opts) {
|
||||
return 'simple(' + this.value + ')'
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the simple value onto the CBOR stream
|
||||
*
|
||||
* @param {Object} gen The generator to push onto
|
||||
*/
|
||||
encodeCBOR(gen) {
|
||||
return gen._pushInt(this.value, MT.SIMPLE_FLOAT)
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the given object a Simple?
|
||||
*
|
||||
* @param {any} obj - object to test
|
||||
* @returns {boolean} - is it Simple?
|
||||
*/
|
||||
static isSimple(obj) {
|
||||
return obj instanceof Simple
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode from the CBOR additional information into a JavaScript value.
|
||||
* If the CBOR item has no parent, return a "safe" symbol instead of
|
||||
* `null` or `undefined`, so that the value can be passed through a
|
||||
* stream in object mode.
|
||||
*
|
||||
* @param {number} val - the CBOR additional info to convert
|
||||
* @param {boolean} [has_parent=true] - Does the CBOR item have a parent?
|
||||
* @param {boolean} [parent_indefinite=false] - Is the parent element
|
||||
* indefinitely encoded?
|
||||
* @returns {(null|undefined|boolean|Symbol|Simple)} - the decoded value
|
||||
*/
|
||||
static decode(val, has_parent=true, parent_indefinite=false) {
|
||||
switch (val) {
|
||||
case SIMPLE.FALSE:
|
||||
return false
|
||||
case SIMPLE.TRUE:
|
||||
return true
|
||||
case SIMPLE.NULL:
|
||||
if (has_parent) {
|
||||
return null
|
||||
} else {
|
||||
return SYMS.NULL
|
||||
}
|
||||
case SIMPLE.UNDEFINED:
|
||||
if (has_parent) {
|
||||
return void 0
|
||||
} else {
|
||||
return SYMS.UNDEFINED
|
||||
}
|
||||
case -1:
|
||||
if (!has_parent || !parent_indefinite) {
|
||||
throw new Error('Invalid BREAK')
|
||||
}
|
||||
return SYMS.BREAK
|
||||
default:
|
||||
return new Simple(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Simple
|
||||
116
node_modules/cbor/lib/tagged.js
generated
vendored
Normal file
116
node_modules/cbor/lib/tagged.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
'use strict'
|
||||
|
||||
const bignumber = require('bignumber.js').BigNumber
|
||||
const utils = require('./utils')
|
||||
const url = require('url')
|
||||
|
||||
const MINUS_ONE = new bignumber(-1)
|
||||
const TEN = new bignumber(10)
|
||||
const TWO = new bignumber(2)
|
||||
|
||||
/**
|
||||
* A CBOR tagged item, where the tag does not have semantics specified at the
|
||||
* moment, or those semantics threw an error during parsing. Typically this will
|
||||
* be an extension point you're not yet expecting.
|
||||
*/
|
||||
class Tagged {
|
||||
|
||||
/**
|
||||
* Creates an instance of Tagged.
|
||||
*
|
||||
* @param {number} tag - the number of the tag
|
||||
* @param {any} value - the value inside the tag
|
||||
* @param {Error} [err] - the error that was thrown parsing the tag, or null
|
||||
*/
|
||||
constructor(tag, value, err) {
|
||||
this.tag = tag
|
||||
this.value = value
|
||||
this.err = err
|
||||
if (typeof this.tag !== 'number') {
|
||||
throw new Error('Invalid tag type (' + (typeof this.tag) + ')')
|
||||
}
|
||||
if ((this.tag < 0) || ((this.tag | 0) !== this.tag)) {
|
||||
throw new Error('Tag must be a positive integer: ' + this.tag)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to a String
|
||||
*
|
||||
* @returns {string} string of the form '1(2)'
|
||||
*/
|
||||
toString() {
|
||||
return `${this.tag}(${JSON.stringify(this.value)})`
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the simple value onto the CBOR stream
|
||||
*
|
||||
* @param {Object} gen The generator to push onto
|
||||
*/
|
||||
encodeCBOR(gen) {
|
||||
gen._pushTag(this.tag)
|
||||
return gen.pushAny(this.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* If we have a converter for this type, do the conversion. Some converters
|
||||
* are built-in. Additional ones can be passed in. If you want to remove
|
||||
* a built-in converter, pass a converter in whose value is 'null' instead
|
||||
* of a function.
|
||||
*
|
||||
* @param {Object} converters - keys in the object are a tag number, the value
|
||||
* is a function that takes the decoded CBOR and returns a JavaScript value
|
||||
* of the appropriate type. Throw an exception in the function on errors.
|
||||
* @returns {any} - the converted item
|
||||
*/
|
||||
convert(converters) {
|
||||
let f = converters != null ? converters[this.tag] : void 0
|
||||
if (typeof f !== 'function') {
|
||||
f = Tagged['_tag_' + this.tag]
|
||||
if (typeof f !== 'function') {
|
||||
return this
|
||||
}
|
||||
}
|
||||
try {
|
||||
return f.call(Tagged, this.value)
|
||||
} catch (error) {
|
||||
this.err = error
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
static _tag_0(v) {
|
||||
return new Date(v)
|
||||
}
|
||||
|
||||
static _tag_1(v) {
|
||||
return new Date(v * 1000)
|
||||
}
|
||||
|
||||
static _tag_2(v) {
|
||||
return utils.bufferToBignumber(v)
|
||||
}
|
||||
|
||||
static _tag_3(v) {
|
||||
return MINUS_ONE.minus(utils.bufferToBignumber(v))
|
||||
}
|
||||
|
||||
static _tag_4(v) {
|
||||
return TEN.pow(v[0]).times(v[1])
|
||||
}
|
||||
|
||||
static _tag_5(v) {
|
||||
return TWO.pow(v[0]).times(v[1])
|
||||
}
|
||||
|
||||
static _tag_32(v) {
|
||||
return url.parse(v)
|
||||
}
|
||||
|
||||
static _tag_35(v) {
|
||||
return new RegExp(v)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Tagged
|
||||
241
node_modules/cbor/lib/utils.js
generated
vendored
Normal file
241
node_modules/cbor/lib/utils.js
generated
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
'use strict'
|
||||
|
||||
const util = require('util')
|
||||
const bignumber = require('bignumber.js').BigNumber
|
||||
|
||||
const constants = require('./constants')
|
||||
const NUMBYTES = constants.NUMBYTES
|
||||
const SHIFT32 = constants.SHIFT32
|
||||
const MAX_SAFE_HIGH = 0x1fffff
|
||||
|
||||
exports.hasBigInt = (typeof BigInt === 'function')
|
||||
|
||||
/**
|
||||
* Convert a UTF8-encoded Buffer to a JS string. If possible, throw an error
|
||||
* on invalid UTF8. Byte Order Marks are not looked at or stripped.
|
||||
*/
|
||||
const TD = (typeof TextDecoder === 'function') ? TextDecoder : util.TextDecoder
|
||||
/* istanbul ignore else */
|
||||
if (TD) {
|
||||
// node 11+, browsers : node 8.3+
|
||||
const td = new TD('utf8', {fatal: true, ignoreBOM: true})
|
||||
exports.utf8 = (buf) => td.decode(buf)
|
||||
exports.utf8.checksUTF8 = true
|
||||
} else {
|
||||
// TODO: polyfill a slow one or wait for node6 to die
|
||||
exports.utf8 = (buf) => buf.toString('utf8')
|
||||
exports.utf8.checksUTF8 = false
|
||||
}
|
||||
|
||||
exports.parseCBORint = function(ai, buf) {
|
||||
switch (ai) {
|
||||
case NUMBYTES.ONE:
|
||||
return buf.readUInt8(0)
|
||||
case NUMBYTES.TWO:
|
||||
return buf.readUInt16BE(0)
|
||||
case NUMBYTES.FOUR:
|
||||
return buf.readUInt32BE(0)
|
||||
case NUMBYTES.EIGHT:
|
||||
const f = buf.readUInt32BE(0)
|
||||
const g = buf.readUInt32BE(4)
|
||||
if (f > MAX_SAFE_HIGH) {
|
||||
return new bignumber(f).times(SHIFT32).plus(g)
|
||||
} else {
|
||||
return (f * SHIFT32) + g
|
||||
}
|
||||
default:
|
||||
throw new Error('Invalid additional info for int: ' + ai)
|
||||
}
|
||||
}
|
||||
|
||||
exports.writeHalf = function writeHalf(buf, half) {
|
||||
// assume 0, -0, NaN, Infinity, and -Infinity have already been caught
|
||||
|
||||
// HACK: everyone settle in. This isn't going to be pretty.
|
||||
// Translate cn-cbor's C code (from Carsten Borman):
|
||||
|
||||
// uint32_t be32;
|
||||
// uint16_t be16, u16;
|
||||
// union {
|
||||
// float f;
|
||||
// uint32_t u;
|
||||
// } u32;
|
||||
// u32.f = float_val;
|
||||
|
||||
const u32 = Buffer.allocUnsafe(4)
|
||||
u32.writeFloatBE(half, 0)
|
||||
const u = u32.readUInt32BE(0)
|
||||
|
||||
// if ((u32.u & 0x1FFF) == 0) { /* worth trying half */
|
||||
|
||||
// hildjj: If the lower 13 bits are 0,
|
||||
// we won't lose anything in the conversion
|
||||
if ((u & 0x1FFF) !== 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
// int s16 = (u32.u >> 16) & 0x8000;
|
||||
// int exp = (u32.u >> 23) & 0xff;
|
||||
// int mant = u32.u & 0x7fffff;
|
||||
|
||||
let s16 = (u >> 16) & 0x8000 // top bit is sign
|
||||
const exp = (u >> 23) & 0xff // then 5 bits of exponent
|
||||
const mant = u & 0x7fffff
|
||||
|
||||
// if (exp == 0 && mant == 0)
|
||||
// ; /* 0.0, -0.0 */
|
||||
|
||||
// hildjj: zeros already handled. Assert if you don't believe me.
|
||||
|
||||
// else if (exp >= 113 && exp <= 142) /* normalized */
|
||||
// s16 += ((exp - 112) << 10) + (mant >> 13);
|
||||
|
||||
if ((exp >= 113) && (exp <= 142)) {
|
||||
s16 += ((exp - 112) << 10) + (mant >> 13)
|
||||
} else if ((exp >= 103) && (exp < 113)) {
|
||||
// else if (exp >= 103 && exp < 113) { /* denorm, exp16 = 0 */
|
||||
// if (mant & ((1 << (126 - exp)) - 1))
|
||||
// goto float32; /* loss of precision */
|
||||
// s16 += ((mant + 0x800000) >> (126 - exp));
|
||||
|
||||
if (mant & ((1 << (126 - exp)) - 1)) {
|
||||
return false
|
||||
}
|
||||
s16 += ((mant + 0x800000) >> (126 - exp))
|
||||
} else {
|
||||
// } else if (exp == 255 && mant == 0) { /* Inf */
|
||||
// s16 += 0x7c00;
|
||||
|
||||
// hildjj: Infinity already handled
|
||||
|
||||
// } else
|
||||
// goto float32; /* loss of range */
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ensure_writable(3);
|
||||
// u16 = s16;
|
||||
// be16 = hton16p((const uint8_t*)&u16);
|
||||
buf.writeUInt16BE(s16)
|
||||
return true
|
||||
}
|
||||
|
||||
exports.parseHalf = function parseHalf(buf) {
|
||||
const sign = buf[0] & 0x80 ? -1 : 1
|
||||
const exp = (buf[0] & 0x7C) >> 2
|
||||
const mant = ((buf[0] & 0x03) << 8) | buf[1]
|
||||
if (!exp) {
|
||||
return sign * 5.9604644775390625e-8 * mant
|
||||
} else if (exp === 0x1f) {
|
||||
return sign * (mant ? 0 / 0 : 2e308)
|
||||
} else {
|
||||
return sign * Math.pow(2, exp - 25) * (1024 + mant)
|
||||
}
|
||||
}
|
||||
|
||||
exports.parseCBORfloat = function parseCBORfloat(buf) {
|
||||
switch (buf.length) {
|
||||
case 2:
|
||||
return exports.parseHalf(buf)
|
||||
case 4:
|
||||
return buf.readFloatBE(0)
|
||||
case 8:
|
||||
return buf.readDoubleBE(0)
|
||||
default:
|
||||
throw new Error('Invalid float size: ' + buf.length)
|
||||
}
|
||||
}
|
||||
|
||||
exports.hex = function hex(s) {
|
||||
return Buffer.from(s.replace(/^0x/, ''), 'hex')
|
||||
}
|
||||
|
||||
exports.bin = function bin(s) {
|
||||
s = s.replace(/\s/g, '')
|
||||
let start = 0
|
||||
let end = (s.length % 8) || 8
|
||||
const chunks = []
|
||||
while (end <= s.length) {
|
||||
chunks.push(parseInt(s.slice(start, end), 2))
|
||||
start = end
|
||||
end += 8
|
||||
}
|
||||
return Buffer.from(chunks)
|
||||
}
|
||||
|
||||
exports.extend = function extend(old={}, ...adds) {
|
||||
const len = adds.length
|
||||
for (let j = 0; j < len; j++) {
|
||||
const a = adds[j]
|
||||
for (const k in a) {
|
||||
const v = a[k]
|
||||
old[k] = v
|
||||
}
|
||||
}
|
||||
return old
|
||||
}
|
||||
|
||||
exports.arrayEqual = function arrayEqual(a, b) {
|
||||
if ((a == null) && (b == null)) {
|
||||
return true
|
||||
}
|
||||
if ((a == null) || (b == null)) {
|
||||
return false
|
||||
}
|
||||
return (a.length === b.length) && a.every((elem, i) => elem === b[i])
|
||||
}
|
||||
|
||||
exports.bufferEqual = function bufferEqual(a, b) {
|
||||
if ((a == null) && (b == null)) {
|
||||
return true
|
||||
}
|
||||
if ((a == null) || (b == null)) {
|
||||
return false
|
||||
}
|
||||
if (!(Buffer.isBuffer(a) && Buffer.isBuffer(b) && (a.length === b.length))) {
|
||||
return false
|
||||
}
|
||||
const len = a.length
|
||||
let ret = true
|
||||
let i
|
||||
let j
|
||||
for (i = j = 0; j < len; i = ++j) {
|
||||
const byte = a[i]
|
||||
ret = ret && (b[i] === byte)
|
||||
}
|
||||
return !!ret
|
||||
}
|
||||
|
||||
exports.bufferToBignumber = function bufferToBignumber(buf) {
|
||||
return new bignumber(buf.toString('hex'), 16)
|
||||
}
|
||||
|
||||
exports.toBigInt = function toBigInt(num) {
|
||||
if (!exports.hasBigInt) {
|
||||
return Number(num) // lossy. Better than nothing?
|
||||
}
|
||||
return BigInt(num)
|
||||
}
|
||||
|
||||
exports.bigIntize = function bigIntize(obj) {
|
||||
const ret = {}
|
||||
for (const k in obj) { // stupid node 6
|
||||
ret[k] = exports.toBigInt(obj[k])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
exports.bufferToBigInt = function bufferToBigInt(buf) {
|
||||
return exports.toBigInt('0x' + buf.toString('hex'))
|
||||
}
|
||||
|
||||
exports.guessEncoding = function guessEncoding(input) {
|
||||
if (typeof input == 'string') {
|
||||
return 'hex'
|
||||
} else if (Buffer.isBuffer(input)) {
|
||||
return undefined
|
||||
}
|
||||
throw new Error('Unknown input type')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user