@stricahq/cbors
Version:
cbor encoder and decoder with annotation
222 lines (221 loc) • 7.75 kB
JavaScript
;
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);
};