node-ejs-renderer/node_modules/@jsonjoy.com/json-pack/lib/util/CompressionTable.js
2024-06-09 13:55:01 -04:00

169 lines
5.8 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompressionTable = void 0;
const JsonPackExtension_1 = require("../JsonPackExtension");
const isSafeInteger = Number.isSafeInteger;
class CompressionTable {
constructor() {
this.integers = new Set();
this.nonIntegers = new Set();
this.table = [];
this.map = new Map();
}
static create(value) {
const table = new CompressionTable();
table.walk(value);
table.finalize();
return table;
}
addInteger(int) {
this.integers.add(int);
}
addLiteral(value) {
if (isSafeInteger(value)) {
this.addInteger(value);
return;
}
this.nonIntegers.add(value);
}
walk(value) {
switch (typeof value) {
case 'object': {
if (!value)
return this.addLiteral(null);
const constructor = value.constructor;
switch (constructor) {
case Object: {
const obj = value;
for (const key in obj) {
this.addLiteral(key);
this.walk(obj[key]);
}
break;
}
case Array: {
const arr = value;
const len = arr.length;
for (let i = 0; i < len; i++)
this.walk(arr[i]);
break;
}
case Map: {
const map = value;
map.forEach((value, key) => {
this.walk(key);
this.walk(value);
});
break;
}
case Set: {
const set = value;
set.forEach((value) => {
this.walk(value);
});
break;
}
case JsonPackExtension_1.JsonPackExtension: {
const ext = value;
this.addInteger(ext.tag);
this.walk(ext.val);
}
}
return;
}
default:
return this.addLiteral(value);
}
}
finalize() {
const integers = Array.from(this.integers);
integers.sort((a, b) => a - b);
const len = integers.length;
const table = this.table;
const map = this.map;
if (len > 0) {
const first = integers[0];
table.push(first);
map.set(first, 0);
let last = first;
for (let i = 1; i < len; i++) {
const int = integers[i];
table.push(int - last);
map.set(int, i);
last = int;
}
}
const nonIntegers = Array.from(this.nonIntegers);
nonIntegers.sort();
const lenNonIntegers = nonIntegers.length;
for (let i = 0; i < lenNonIntegers; i++) {
const value = nonIntegers[i];
table.push(value);
map.set(value, len + i);
}
this.integers.clear();
this.nonIntegers.clear();
}
getIndex(value) {
const index = this.map.get(value);
if (index === undefined)
throw new Error(`Value [${value}] not found in compression table.`);
return index;
}
getTable() {
return this.table;
}
compress(value) {
switch (typeof value) {
case 'object': {
if (!value)
return this.getIndex(null);
const constructor = value.constructor;
switch (constructor) {
case Object: {
const obj = value;
const newObj = {};
for (const key in obj)
newObj[this.getIndex(key)] = this.compress(obj[key]);
return newObj;
}
case Array: {
const arr = value;
const newArr = [];
const len = arr.length;
for (let i = 0; i < len; i++)
newArr.push(this.compress(arr[i]));
return newArr;
}
case Map: {
const map = value;
const newMap = new Map();
map.forEach((value, key) => {
newMap.set(this.compress(key), this.compress(value));
});
return newMap;
}
case Set: {
const set = value;
const newSet = new Set();
set.forEach((value) => {
newSet.add(this.compress(value));
});
break;
}
case JsonPackExtension_1.JsonPackExtension: {
const ext = value;
const newExt = new JsonPackExtension_1.JsonPackExtension(this.getIndex(ext.tag), this.compress(ext.val));
return newExt;
}
}
throw new Error('UNEXPECTED_OBJECT');
}
default: {
return this.getIndex(value);
}
}
}
}
exports.CompressionTable = CompressionTable;
//# sourceMappingURL=CompressionTable.js.map