UNPKG

@stricahq/cbors

Version:

cbor encoder and decoder with annotation

222 lines (221 loc) 7.75 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-disable no-bitwise */ const buffer_1 = require("buffer"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const _1 = require("."); const helpers_1 = require("./helpers"); const utils_1 = require("./utils"); const NAN_BUF = buffer_1.Buffer.from('f97e00', 'hex'); const BREAK = buffer_1.Buffer.from('ff', 'hex'); exports.default = (input, options = { collapseBigNumber: true }) => { const outBufAry = []; function pushFloat64(value) { const buf = buffer_1.Buffer.allocUnsafe(8); buf.writeDoubleBE(value); outBufAry.push(buf); } function pushUInt8(value) { const buf = buffer_1.Buffer.allocUnsafe(1); buf.writeUInt8(value, 0); outBufAry.push(buf); } function pushBuffer(value) { outBufAry.push(value); } function pushUInt16(value) { const buf = buffer_1.Buffer.allocUnsafe(2); buf.writeUInt16BE(value, 0); outBufAry.push(buf); } function pushUInt32(value) { const buf = buffer_1.Buffer.allocUnsafe(4); buf.writeUInt32BE(value, 0); outBufAry.push(buf); } function pushUInt64(value) { const low = value % utils_1.POW_2_32; const high = (value - low) / utils_1.POW_2_32; const buf = buffer_1.Buffer.allocUnsafe(8); buf.writeUInt32BE(high, 0); buf.writeUInt32BE(low, 4); outBufAry.push(buf); } function pushTypeAndLength(type, length) { if (length < 24) { pushUInt8((type << 5) | length); } else if (length < 0x100) { pushUInt8((type << 5) | 24); pushUInt8(length); } else if (length < 0x10000) { pushUInt8((type << 5) | 25); pushUInt16(length); } else if (length < 0x100000000) { pushUInt8((type << 5) | 26); pushUInt32(length); } else { pushUInt8((type << 5) | 27); pushUInt64(length); } } function pushIntNum(value) { if (Object.is(value, -0)) { return pushBuffer(buffer_1.Buffer.from('f98000', 'hex')); } if (value >= 0 && value <= utils_1.POW_2_53) { return pushTypeAndLength(0, value); } if (-utils_1.POW_2_53 <= value && value < 0) { return pushTypeAndLength(1, -(value + 1)); } } function pushBigInt(value) { let valueM = value; let type = 0; let tag = 2; if (valueM.isNegative()) { valueM = valueM.negated().minus(1); type = 1; tag = 3; } if (options.collapseBigNumber && valueM.lte(utils_1.MAX_BIG_NUM_INT64)) { if (valueM.lte(utils_1.MAX_BIG_NUM_INT32)) { return pushTypeAndLength(type, valueM.toNumber()); } pushUInt8((type << 5) | 27); pushUInt32(valueM.dividedToIntegerBy(utils_1.SHIFT32).toNumber()); pushUInt32(valueM.mod(utils_1.SHIFT32).toNumber()); } else { let str = valueM.toString(16); if (str.length % 2) { str = `0${str}`; } // push tag pushTypeAndLength(6, tag); // push buffer const buf = buffer_1.Buffer.from(str, 'hex'); pushTypeAndLength(2, buf.length); pushBuffer(buf); } } function pushBigNumber(value) { if (value.isNaN()) { pushBuffer(NAN_BUF); } else if (value.isInteger()) { pushBigInt(value); } else { // push decimal pushTypeAndLength(6, 4); pushTypeAndLength(4, 2); const dec = value.decimalPlaces(); const slide = value.shiftedBy(dec); pushIntNum(-dec); if (slide.abs().isLessThan(utils_1.MAX_BIG_NUM_INT)) { pushIntNum(slide.toNumber()); } else { pushBigInt(slide); } } } function encodeItem(value) { if (value === false) return pushUInt8(0xf4); if (value === true) return pushUInt8(0xf5); if (value === null) return pushUInt8(0xf6); if (value === undefined) return pushUInt8(0xf7); switch (typeof value) { case 'number': { if (Math.round(value) === value) { return pushIntNum(value); } pushUInt8(0xfb); return pushFloat64(value); } case 'string': { const strBuff = buffer_1.Buffer.from(value, 'utf8'); pushTypeAndLength(3, strBuff.length); return pushBuffer(strBuff); } default: { if (Array.isArray(value)) { if (value instanceof helpers_1.IndefiniteArray) { pushUInt8((4 << 5) | 31); } else { pushTypeAndLength(4, value.length); } for (const v of value) { encodeItem(v); } if (value instanceof helpers_1.IndefiniteArray) { pushBuffer(BREAK); } } else if (value instanceof buffer_1.Buffer) { pushTypeAndLength(2, value.length); pushBuffer(value); } else if (value instanceof ArrayBuffer) { const buf = buffer_1.Buffer.from(value); pushTypeAndLength(2, buf.length); pushBuffer(buf); } else if (value instanceof Uint8ClampedArray) { const buf = buffer_1.Buffer.from(value); pushTypeAndLength(2, buf.length); pushBuffer(buf); } else if (value instanceof Uint8Array) { const buf = buffer_1.Buffer.from(value); pushTypeAndLength(2, buf.length); pushBuffer(buf); } else if (bignumber_js_1.default.isBigNumber(value)) { pushBigNumber(value); } else if (value instanceof _1.CborTag) { pushTypeAndLength(6, value.tag); encodeItem(value.value); } else { let entries; if (value instanceof Map) { entries = [...value.entries()]; } else { entries = [...Object.entries(value)]; } if (value instanceof helpers_1.IndefiniteMap) { pushUInt8((5 << 5) | 31); } else { pushTypeAndLength(5, entries.length); } for (const [key, v] of entries) { encodeItem(key); encodeItem(v); } if (value instanceof helpers_1.IndefiniteMap) { pushBuffer(BREAK); } } } } } encodeItem(input); return buffer_1.Buffer.concat(outBufAry); };