@jsonjoy.com/json-pack
Version:
High-performance JSON serialization library
242 lines • 7.72 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IonDecoderBase = void 0;
const tslib_1 = require("tslib");
const Reader_1 = require("@jsonjoy.com/buffers/lib/Reader");
const sharedCachedUtf8Decoder_1 = tslib_1.__importDefault(require("@jsonjoy.com/buffers/lib/utf8/sharedCachedUtf8Decoder"));
const Import_1 = require("./Import");
class IonDecoderBase {
constructor(reader) {
this.reader = (reader ?? new Reader_1.Reader());
this.utf8Decoder = sharedCachedUtf8Decoder_1.default;
}
val() {
const typedesc = this.reader.u8();
const type = (typedesc >> 4) & 0xf;
const length = typedesc & 0xf;
switch (type) {
case 0:
return this.readNull(length);
case 1:
return this.readBool(length);
case 2:
return this.readUint(length);
case 3:
return this.readNint(length);
case 4:
return this.readFloat(length);
case 8:
return this.readString(length);
case 10:
return this.readBinary(length);
case 11:
return this.readList(length);
case 13:
return this.readStruct(length);
case 14:
return this.readAnnotation(length);
default:
throw new Error(`Unknown Ion type: 0x${type.toString(16)}`);
}
}
readNull(length) {
if (length === 15)
return null;
if (length === 0) {
this.val();
return null;
}
if (length === 14) {
const padLength = this.readVUint();
this.reader.x += padLength;
this.val();
return null;
}
this.reader.x += length;
this.val();
return null;
}
readBool(length) {
if (length === 15)
return null;
if (length === 0)
return false;
if (length === 1)
return true;
throw new Error(`Invalid bool length: ${length}`);
}
readUint(length) {
if (length === 15)
return null;
if (length === 0)
return 0;
let value = 0;
for (let i = 0; i < length; i++) {
value = value * 256 + this.reader.u8();
}
return value;
}
readNint(length) {
if (length === 15)
return null;
if (length === 0)
throw new Error('Negative zero is illegal');
let value = 0;
for (let i = 0; i < length; i++) {
value = value * 256 + this.reader.u8();
}
return -value;
}
readFloat(length) {
if (length === 15)
return null;
if (length === 0)
return 0.0;
if (length === 4)
return this.reader.f32();
if (length === 8)
return this.reader.f64();
throw new Error(`Unsupported float length: ${length}`);
}
readString(length) {
if (length === 15)
return null;
let actualLength = length;
if (length === 14) {
actualLength = this.readVUint();
}
if (actualLength === 0)
return '';
return this.reader.utf8(actualLength);
}
readBinary(length) {
if (length === 15)
return null;
let actualLength = length;
if (length === 14) {
actualLength = this.readVUint();
}
if (actualLength === 0)
return new Uint8Array(0);
return this.reader.buf(actualLength);
}
readList(length) {
if (length === 15)
return null;
let actualLength = length;
if (length === 14) {
actualLength = this.readVUint();
}
if (actualLength === 0)
return [];
const endPos = this.reader.x + actualLength;
const list = [];
while (this.reader.x < endPos) {
list.push(this.val());
}
if (this.reader.x !== endPos) {
throw new Error('List parsing error: incorrect length');
}
return list;
}
readStruct(length) {
if (length === 15)
return null;
let actualLength = length;
if (length === 14) {
actualLength = this.readVUint();
}
if (actualLength === 0)
return {};
const endPos = this.reader.x + actualLength;
const struct = {};
while (this.reader.x < endPos) {
const fieldNameId = this.readVUint();
const fieldName = this.getSymbolText(fieldNameId);
const fieldValue = this.val();
struct[fieldName] = fieldValue;
}
if (this.reader.x !== endPos) {
throw new Error('Struct parsing error: incorrect length');
}
return struct;
}
readAnnotation(length) {
if (length < 3) {
throw new Error('Annotation wrapper must have at least 3 bytes');
}
let actualLength = length;
if (length === 14) {
actualLength = this.readVUint();
}
const annotLength = this.readVUint();
const endAnnotPos = this.reader.x + annotLength;
while (this.reader.x < endAnnotPos) {
this.readVUint();
}
if (this.reader.x !== endAnnotPos) {
throw new Error('Annotation parsing error: incorrect annotation length');
}
return this.val();
}
readVUint() {
let value = 0;
let byte;
do {
byte = this.reader.u8();
value = (value << 7) | (byte & 0x7f);
} while ((byte & 0x80) === 0);
return value;
}
readVInt() {
const firstByte = this.reader.u8();
if (firstByte & 0x80) {
const sign = firstByte & 0x40 ? -1 : 1;
const magnitude = firstByte & 0x3f;
return sign * magnitude;
}
const sign = firstByte & 0x40 ? -1 : 1;
let magnitude = firstByte & 0x3f;
let byte;
do {
byte = this.reader.u8();
magnitude = (magnitude << 7) | (byte & 0x7f);
} while ((byte & 0x80) === 0);
return sign * magnitude;
}
getSymbolText(symbolId) {
if (!this.symbols) {
throw new Error('No symbol table available');
}
const symbol = this.symbols.getText(symbolId);
if (symbol === undefined) {
throw new Error(`Unknown symbol ID: ${symbolId}`);
}
return symbol;
}
validateBVM() {
const bvm = this.reader.u32();
if (bvm !== 0xe00100ea) {
throw new Error(`Invalid Ion Binary Version Marker: 0x${bvm.toString(16)}`);
}
}
readSymbolTable() {
if (this.reader.x < this.reader.uint8.length) {
const nextByte = this.reader.peak();
const type = (nextByte >> 4) & 0xf;
if (type === 14) {
const annotValue = this.val();
if (annotValue && typeof annotValue === 'object' && !Array.isArray(annotValue)) {
const symbolsKey = 'symbols';
const obj = annotValue;
if (symbolsKey in obj && Array.isArray(obj[symbolsKey])) {
const newSymbols = obj[symbolsKey];
this.symbols = new Import_1.Import(this.symbols || null, newSymbols);
}
}
}
}
}
}
exports.IonDecoderBase = IonDecoderBase;
//# sourceMappingURL=IonDecoderBase.js.map