Spaces:
Running
Running
; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
exports.BsonEncoder = void 0; | |
const values_1 = require("./values"); | |
class BsonEncoder { | |
constructor(writer) { | |
this.writer = writer; | |
} | |
encode(value) { | |
const writer = this.writer; | |
writer.reset(); | |
this.writeAny(value); | |
return writer.flush(); | |
} | |
writeAny(value) { | |
switch (typeof value) { | |
case 'object': { | |
if (value === null) | |
throw new Error('NOT_OBJ'); | |
return this.writeObj(value); | |
} | |
} | |
throw new Error('NOT_OBJ'); | |
} | |
writeNull() { | |
throw new Error('Method not implemented.'); | |
} | |
writeUndef() { | |
throw new Error('Method not implemented.'); | |
} | |
writeBoolean(bool) { | |
throw new Error('Method not implemented.'); | |
} | |
writeNumber(num) { | |
throw new Error('Method not implemented.'); | |
} | |
writeInteger(int) { | |
throw new Error('Method not implemented.'); | |
} | |
writeUInteger(uint) { | |
throw new Error('Method not implemented.'); | |
} | |
writeInt32(int) { | |
const writer = this.writer; | |
writer.ensureCapacity(4); | |
writer.view.setInt32(writer.x, int, true); | |
writer.x += 4; | |
} | |
writeInt64(int) { | |
const writer = this.writer; | |
writer.ensureCapacity(8); | |
writer.view.setBigInt64(writer.x, BigInt(int), true); | |
writer.x += 8; | |
} | |
writeFloat(float) { | |
const writer = this.writer; | |
writer.ensureCapacity(4); | |
writer.view.setFloat64(writer.x, float, true); | |
writer.x += 8; | |
} | |
writeBigInt(int) { | |
throw new Error('Method not implemented.'); | |
} | |
writeBin(buf) { | |
const length = buf.length; | |
this.writeInt32(length); | |
const writer = this.writer; | |
writer.u8(0); | |
writer.buf(buf, length); | |
} | |
writeStr(str) { | |
const writer = this.writer; | |
const length = str.length; | |
const maxSize = 4 + 1 + 4 * length; | |
writer.ensureCapacity(maxSize); | |
const x = writer.x; | |
this.writeInt32(length + 1); | |
const bytesWritten = writer.utf8(str); | |
writer.u8(0); | |
if (bytesWritten !== length) { | |
writer.view.setInt32(x, bytesWritten + 1, true); | |
} | |
} | |
writeAsciiStr(str) { | |
throw new Error('Method not implemented.'); | |
} | |
writeArr(arr) { | |
this.writeObj(arr); | |
} | |
writeObj(obj) { | |
const writer = this.writer; | |
writer.ensureCapacity(8); | |
const x0 = writer.x0; | |
const dx = writer.x - x0; | |
writer.x += 4; | |
const keys = Object.keys(obj); | |
const length = keys.length; | |
for (let i = 0; i < length; i++) { | |
const key = keys[i]; | |
const value = obj[key]; | |
this.writeKey(key, value); | |
} | |
writer.u8(0); | |
const x = writer.x0 + dx; | |
const size = writer.x - x; | |
writer.view.setUint32(x, size, true); | |
} | |
writeCString(str) { | |
const writer = this.writer; | |
const length = str.length; | |
writer.ensureCapacity(1 + 4 * length); | |
const uint8 = writer.uint8; | |
let x = writer.x; | |
let pos = 0; | |
while (pos < length) { | |
let value = str.charCodeAt(pos++); | |
if ((value & 0xffffff80) === 0) { | |
if (!value) | |
break; | |
uint8[x++] = value; | |
continue; | |
} | |
else if ((value & 0xfffff800) === 0) { | |
const octet = ((value >> 6) & 0x1f) | 0xc0; | |
if (!octet) | |
break; | |
uint8[x++] = octet; | |
} | |
else { | |
if (value >= 0xd800 && value <= 0xdbff) { | |
if (pos < length) { | |
const extra = str.charCodeAt(pos); | |
if ((extra & 0xfc00) === 0xdc00) { | |
pos++; | |
value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; | |
} | |
} | |
} | |
if ((value & 0xffff0000) === 0) { | |
const octet1 = ((value >> 12) & 0x0f) | 0xe0; | |
const octet2 = ((value >> 6) & 0x3f) | 0x80; | |
if (!octet1 || !octet2) | |
throw new Error('INVALID_CSTRING'); | |
uint8[x++] = octet1; | |
uint8[x++] = octet2; | |
} | |
else { | |
const octet1 = ((value >> 18) & 0x07) | 0xf0; | |
const octet2 = ((value >> 12) & 0x3f) | 0x80; | |
const octet3 = ((value >> 6) & 0x3f) | 0x80; | |
if (!octet1 || !octet2 || !octet3) | |
throw new Error('INVALID_CSTRING'); | |
uint8[x++] = octet1; | |
uint8[x++] = octet2; | |
uint8[x++] = octet3; | |
} | |
} | |
const octet = (value & 0x3f) | 0x80; | |
if (!octet) | |
break; | |
uint8[x++] = octet; | |
} | |
uint8[x++] = 0; | |
writer.x = x; | |
} | |
writeObjectId(id) { | |
const writer = this.writer; | |
writer.ensureCapacity(12); | |
const uint8 = writer.uint8; | |
const x = writer.x; | |
const { timestamp, process, counter } = id; | |
uint8[x + 0] = timestamp >>> 24; | |
uint8[x + 1] = (timestamp >>> 16) & 0xff; | |
uint8[x + 2] = (timestamp >>> 8) & 0xff; | |
uint8[x + 3] = timestamp & 0xff; | |
uint8[x + 4] = process & 0xff; | |
uint8[x + 5] = (process >>> 8) & 0xff; | |
uint8[x + 6] = (process >>> 16) & 0xff; | |
uint8[x + 7] = (process >>> 24) & 0xff; | |
let lo32 = process | 0; | |
if (lo32 < 0) | |
lo32 += 4294967296; | |
const hi32 = (process - lo32) / 4294967296; | |
uint8[x + 8] = hi32 & 0xff; | |
uint8[x + 9] = counter >>> 16; | |
uint8[x + 10] = (counter >>> 8) & 0xff; | |
uint8[x + 11] = counter & 0xff; | |
writer.x += 12; | |
} | |
writeKey(key, value) { | |
const writer = this.writer; | |
switch (typeof value) { | |
case 'number': { | |
const isFloat = Math.floor(value) !== value; | |
if (isFloat) { | |
writer.u8(0x01); | |
this.writeCString(key); | |
this.writeFloat(value); | |
break; | |
} | |
if (value <= 2147483647 && value >= -2147483648) { | |
writer.u8(0x10); | |
this.writeCString(key); | |
this.writeInt32(value); | |
break; | |
} | |
writer.u8(0x12); | |
this.writeCString(key); | |
this.writeInt64(value); | |
break; | |
} | |
case 'string': { | |
writer.u8(0x02); | |
this.writeCString(key); | |
this.writeStr(value); | |
break; | |
} | |
case 'object': { | |
if (value === null) { | |
writer.u8(0x0a); | |
this.writeCString(key); | |
break; | |
} | |
const constructor = value.constructor; | |
switch (constructor) { | |
case Object: { | |
writer.u8(0x03); | |
this.writeCString(key); | |
this.writeObj(value); | |
break; | |
} | |
case Array: { | |
writer.u8(0x04); | |
this.writeCString(key); | |
this.writeObj(value); | |
break; | |
} | |
case Uint8Array: { | |
writer.u8(0x05); | |
this.writeCString(key); | |
this.writeBin(value); | |
break; | |
} | |
case values_1.BsonObjectId: { | |
writer.u8(0x07); | |
this.writeCString(key); | |
this.writeObjectId(value); | |
break; | |
} | |
case Date: { | |
writer.u8(0x09); | |
this.writeCString(key); | |
writer.ensureCapacity(8); | |
writer.view.setBigUint64(writer.x, BigInt(value.getTime()), true); | |
writer.x += 8; | |
break; | |
} | |
case RegExp: { | |
writer.u8(0x0b); | |
this.writeCString(key); | |
this.writeCString(value.source); | |
this.writeCString(value.flags); | |
break; | |
} | |
case values_1.BsonDbPointer: { | |
writer.u8(0x0c); | |
this.writeCString(key); | |
const pointer = value; | |
this.writeStr(pointer.name); | |
this.writeObjectId(pointer.id); | |
break; | |
} | |
case values_1.BsonJavascriptCode: { | |
writer.u8(0x0d); | |
this.writeCString(key); | |
this.writeStr(value.code); | |
break; | |
} | |
case values_1.BsonInt32: { | |
writer.u8(0x10); | |
this.writeCString(key); | |
this.writeInt32(value.value); | |
break; | |
} | |
case values_1.BsonInt64: { | |
writer.u8(0x12); | |
this.writeCString(key); | |
this.writeInt64(value.value); | |
break; | |
} | |
case values_1.BsonFloat: { | |
writer.u8(0x01); | |
this.writeCString(key); | |
this.writeFloat(value.value); | |
break; | |
} | |
case values_1.BsonTimestamp: { | |
writer.u8(0x11); | |
this.writeCString(key); | |
const ts = value; | |
this.writeInt32(ts.increment); | |
this.writeInt32(ts.timestamp); | |
break; | |
} | |
case values_1.BsonDecimal128: { | |
writer.u8(0x13); | |
this.writeCString(key); | |
const dec = value; | |
if (dec.data.length !== 16) | |
throw new Error('INVALID_DECIMAL128'); | |
writer.buf(dec.data, 16); | |
break; | |
} | |
case values_1.BsonMinKey: { | |
writer.u8(0xff); | |
this.writeCString(key); | |
break; | |
} | |
case values_1.BsonMaxKey: { | |
writer.u8(0x7f); | |
this.writeCString(key); | |
break; | |
} | |
case values_1.BsonBinary: { | |
writer.u8(0x05); | |
this.writeCString(key); | |
const bin = value; | |
const length = bin.data.length; | |
this.writeInt32(length); | |
writer.u8(bin.subtype); | |
writer.buf(bin.data, length); | |
break; | |
} | |
default: { | |
writer.u8(0x03); | |
this.writeCString(key); | |
this.writeObj(value); | |
break; | |
} | |
} | |
break; | |
} | |
case 'boolean': { | |
writer.u8(0x08); | |
this.writeCString(key); | |
writer.u8(+value); | |
break; | |
} | |
case 'undefined': { | |
writer.u8(0x06); | |
this.writeCString(key); | |
break; | |
} | |
case 'symbol': { | |
writer.u8(0x0e); | |
this.writeCString(key); | |
this.writeStr(value.description || ''); | |
break; | |
} | |
} | |
} | |
} | |
exports.BsonEncoder = BsonEncoder; | |
//# sourceMappingURL=BsonEncoder.js.map |