mirror of https://github.com/ghostfolio/ghostfolio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.2 KiB
187 lines
6.2 KiB
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.BsonDecoder = void 0;
|
|
const Reader_1 = require("@jsonjoy.com/buffers/lib/Reader");
|
|
const values_1 = require("./values");
|
|
class BsonDecoder {
|
|
constructor(reader = new Reader_1.Reader()) {
|
|
this.reader = reader;
|
|
}
|
|
read(uint8) {
|
|
this.reader.reset(uint8);
|
|
return this.readDocument();
|
|
}
|
|
decode(uint8) {
|
|
this.reader.reset(uint8);
|
|
return this.readDocument();
|
|
}
|
|
readAny() {
|
|
return this.readDocument();
|
|
}
|
|
readDocument() {
|
|
const reader = this.reader;
|
|
const documentSize = reader.view.getInt32(reader.x, true);
|
|
reader.x += 4;
|
|
const startPos = reader.x;
|
|
const endPos = startPos + documentSize - 4 - 1;
|
|
const obj = {};
|
|
while (reader.x < endPos) {
|
|
const elementType = reader.u8();
|
|
if (elementType === 0)
|
|
break;
|
|
const key = this.readCString();
|
|
const value = this.readElementValue(elementType);
|
|
obj[key] = value;
|
|
}
|
|
if (reader.x <= endPos) {
|
|
reader.x = startPos + documentSize - 4;
|
|
}
|
|
return obj;
|
|
}
|
|
readCString() {
|
|
const reader = this.reader;
|
|
const uint8 = reader.uint8;
|
|
const x = reader.x;
|
|
let length = 0;
|
|
while (uint8[x + length] !== 0) {
|
|
length++;
|
|
}
|
|
if (length === 0) {
|
|
reader.x++;
|
|
return '';
|
|
}
|
|
const str = reader.utf8(length);
|
|
reader.x++;
|
|
return str;
|
|
}
|
|
readString() {
|
|
const reader = this.reader;
|
|
const length = reader.view.getInt32(reader.x, true);
|
|
reader.x += 4;
|
|
if (length <= 0) {
|
|
throw new Error('Invalid string length');
|
|
}
|
|
const str = reader.utf8(length - 1);
|
|
reader.x++;
|
|
return str;
|
|
}
|
|
readElementValue(type) {
|
|
const reader = this.reader;
|
|
switch (type) {
|
|
case 0x01:
|
|
const doubleVal = reader.view.getFloat64(reader.x, true);
|
|
reader.x += 8;
|
|
return doubleVal;
|
|
case 0x02:
|
|
return this.readString();
|
|
case 0x03:
|
|
return this.readDocument();
|
|
case 0x04:
|
|
return this.readArray();
|
|
case 0x05:
|
|
return this.readBinary();
|
|
case 0x06:
|
|
return undefined;
|
|
case 0x07:
|
|
return this.readObjectId();
|
|
case 0x08:
|
|
return reader.u8() === 1;
|
|
case 0x09:
|
|
const dateVal = reader.view.getBigInt64(reader.x, true);
|
|
reader.x += 8;
|
|
return new Date(Number(dateVal));
|
|
case 0x0a:
|
|
return null;
|
|
case 0x0b:
|
|
return this.readRegex();
|
|
case 0x0c:
|
|
return this.readDbPointer();
|
|
case 0x0d:
|
|
return new values_1.BsonJavascriptCode(this.readString());
|
|
case 0x0e:
|
|
return Symbol(this.readString());
|
|
case 0x0f:
|
|
return this.readCodeWithScope();
|
|
case 0x10:
|
|
const int32Val = reader.view.getInt32(reader.x, true);
|
|
reader.x += 4;
|
|
return int32Val;
|
|
case 0x11:
|
|
return this.readTimestamp();
|
|
case 0x12:
|
|
const int64Val = reader.view.getBigInt64(reader.x, true);
|
|
reader.x += 8;
|
|
return Number(int64Val);
|
|
case 0x13:
|
|
return this.readDecimal128();
|
|
case 0xff:
|
|
return new values_1.BsonMinKey();
|
|
case 0x7f:
|
|
return new values_1.BsonMaxKey();
|
|
default:
|
|
throw new Error(`Unsupported BSON type: 0x${type.toString(16)}`);
|
|
}
|
|
}
|
|
readArray() {
|
|
const doc = this.readDocument();
|
|
const keys = Object.keys(doc).sort((a, b) => parseInt(a, 10) - parseInt(b, 10));
|
|
return keys.map((key) => doc[key]);
|
|
}
|
|
readBinary() {
|
|
const reader = this.reader;
|
|
const length = reader.view.getInt32(reader.x, true);
|
|
reader.x += 4;
|
|
const subtype = reader.u8();
|
|
const data = reader.buf(length);
|
|
if (subtype === 0) {
|
|
return data;
|
|
}
|
|
return new values_1.BsonBinary(subtype, data);
|
|
}
|
|
readObjectId() {
|
|
const reader = this.reader;
|
|
const uint8 = reader.uint8;
|
|
const x = reader.x;
|
|
const timestamp = (uint8[x] << 24) | (uint8[x + 1] << 16) | (uint8[x + 2] << 8) | uint8[x + 3];
|
|
const processLo = uint8[x + 4] | (uint8[x + 5] << 8) | (uint8[x + 6] << 16) | (uint8[x + 7] << 24);
|
|
const processHi = uint8[x + 8];
|
|
const processLoUnsigned = processLo >>> 0;
|
|
const process = processLoUnsigned + processHi * 0x100000000;
|
|
const counter = (uint8[x + 9] << 16) | (uint8[x + 10] << 8) | uint8[x + 11];
|
|
reader.x += 12;
|
|
return new values_1.BsonObjectId(timestamp, process, counter);
|
|
}
|
|
readRegex() {
|
|
const pattern = this.readCString();
|
|
const flags = this.readCString();
|
|
return new RegExp(pattern, flags);
|
|
}
|
|
readDbPointer() {
|
|
const name = this.readString();
|
|
const id = this.readObjectId();
|
|
return new values_1.BsonDbPointer(name, id);
|
|
}
|
|
readCodeWithScope() {
|
|
const reader = this.reader;
|
|
const totalLength = reader.view.getInt32(reader.x, true);
|
|
reader.x += 4;
|
|
const code = this.readString();
|
|
const scope = this.readDocument();
|
|
return new values_1.BsonJavascriptCodeWithScope(code, scope);
|
|
}
|
|
readTimestamp() {
|
|
const reader = this.reader;
|
|
const increment = reader.view.getInt32(reader.x, true);
|
|
reader.x += 4;
|
|
const timestamp = reader.view.getInt32(reader.x, true);
|
|
reader.x += 4;
|
|
return new values_1.BsonTimestamp(increment, timestamp);
|
|
}
|
|
readDecimal128() {
|
|
const reader = this.reader;
|
|
const data = reader.buf(16);
|
|
return new values_1.BsonDecimal128(data);
|
|
}
|
|
}
|
|
exports.BsonDecoder = BsonDecoder;
|
|
//# sourceMappingURL=BsonDecoder.js.map
|