424 lines
12 KiB
JavaScript
424 lines
12 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.RespEncoder = void 0;
|
|
const Writer_1 = require("@jsonjoy.com/util/lib/buffers/Writer");
|
|
const utf8_1 = require("@jsonjoy.com/util/lib/strings/utf8");
|
|
const extensions_1 = require("./extensions");
|
|
const JsonPackExtension_1 = require("../JsonPackExtension");
|
|
const REG_RN = /[\r\n]/;
|
|
const isSafeInteger = Number.isSafeInteger;
|
|
class RespEncoder {
|
|
constructor(writer = new Writer_1.Writer()) {
|
|
this.writer = writer;
|
|
}
|
|
encode(value) {
|
|
this.writeAny(value);
|
|
return this.writer.flush();
|
|
}
|
|
encodeToSlice(value) {
|
|
this.writeAny(value);
|
|
return this.writer.flushSlice();
|
|
}
|
|
writeAny(value) {
|
|
switch (typeof value) {
|
|
case 'number':
|
|
return this.writeNumber(value);
|
|
case 'string':
|
|
return this.writeStr(value);
|
|
case 'boolean':
|
|
return this.writeBoolean(value);
|
|
case 'object': {
|
|
if (!value)
|
|
return this.writeNull();
|
|
if (value instanceof Array)
|
|
return this.writeArr(value);
|
|
if (value instanceof Uint8Array)
|
|
return this.writeBin(value);
|
|
if (value instanceof Error)
|
|
return this.writeErr(value.message);
|
|
if (value instanceof Set)
|
|
return this.writeSet(value);
|
|
if (value instanceof JsonPackExtension_1.JsonPackExtension) {
|
|
if (value instanceof extensions_1.RespPush)
|
|
return this.writePush(value.val);
|
|
if (value instanceof extensions_1.RespVerbatimString)
|
|
return this.writeVerbatimStr('txt', value.val);
|
|
if (value instanceof extensions_1.RespAttributes)
|
|
return this.writeAttr(value.val);
|
|
}
|
|
return this.writeObj(value);
|
|
}
|
|
case 'undefined':
|
|
return this.writeUndef();
|
|
case 'bigint':
|
|
return this.writeBigInt(value);
|
|
default:
|
|
return this.writeUnknown(value);
|
|
}
|
|
}
|
|
writeLength(length) {
|
|
const writer = this.writer;
|
|
if (length < 100) {
|
|
if (length < 10) {
|
|
writer.u8(length + 48);
|
|
return;
|
|
}
|
|
const octet1 = length % 10;
|
|
const octet2 = (length - octet1) / 10;
|
|
writer.u16(((octet2 + 48) << 8) + octet1 + 48);
|
|
return;
|
|
}
|
|
let digits = 1;
|
|
let pow = 10;
|
|
while (length >= pow) {
|
|
digits++;
|
|
pow *= 10;
|
|
}
|
|
writer.ensureCapacity(digits);
|
|
const uint8 = writer.uint8;
|
|
const x = writer.x;
|
|
const newX = x + digits;
|
|
let i = newX - 1;
|
|
while (i >= x) {
|
|
const remainder = length % 10;
|
|
uint8[i--] = remainder + 48;
|
|
length = (length - remainder) / 10;
|
|
}
|
|
writer.x = newX;
|
|
}
|
|
encodeCmd(args) {
|
|
this.writeCmd(args);
|
|
return this.writer.flush();
|
|
}
|
|
writeCmd(args) {
|
|
const length = args.length;
|
|
this.writeArrHdr(length);
|
|
for (let i = 0; i < length; i++) {
|
|
const arg = args[i];
|
|
if (arg instanceof Uint8Array)
|
|
this.writeBin(arg);
|
|
else
|
|
this.writeBulkStrAscii(arg + '');
|
|
}
|
|
}
|
|
encodeCmdUtf8(args) {
|
|
this.writeCmdUtf8(args);
|
|
return this.writer.flush();
|
|
}
|
|
writeCmdUtf8(args) {
|
|
const length = args.length;
|
|
this.writeArrHdr(length);
|
|
for (let i = 0; i < length; i++)
|
|
this.writeArgUtf8(args[i]);
|
|
}
|
|
writeArgUtf8(arg) {
|
|
if (arg instanceof Uint8Array)
|
|
return this.writeBin(arg);
|
|
else
|
|
this.writeBulkStr(arg + '');
|
|
}
|
|
writeNull() {
|
|
this.writer.u8u16(95, 3338);
|
|
}
|
|
writeNullStr() {
|
|
this.writer.u8u32(36, 45 * 0x1000000 +
|
|
49 * 0x10000 +
|
|
3338);
|
|
}
|
|
writeNullArr() {
|
|
this.writer.u8u32(42, 45 * 0x1000000 +
|
|
49 * 0x10000 +
|
|
3338);
|
|
}
|
|
writeBoolean(bool) {
|
|
this.writer.u32(bool
|
|
? 35 * 0x1000000 +
|
|
116 * 0x10000 +
|
|
3338
|
|
: 35 * 0x1000000 +
|
|
102 * 0x10000 +
|
|
3338);
|
|
}
|
|
writeNumber(num) {
|
|
if (isSafeInteger(num))
|
|
this.writeInteger(num);
|
|
else if (typeof num === 'bigint')
|
|
this.writeBigInt(num);
|
|
else
|
|
this.writeFloat(num);
|
|
}
|
|
writeBigInt(int) {
|
|
const writer = this.writer;
|
|
writer.u8(40);
|
|
writer.ascii(int + '');
|
|
writer.u16(3338);
|
|
}
|
|
writeInteger(int) {
|
|
const writer = this.writer;
|
|
writer.u8(58);
|
|
writer.ascii(int + '');
|
|
writer.u16(3338);
|
|
}
|
|
writeUInteger(uint) {
|
|
this.writeInteger(uint);
|
|
}
|
|
writeFloat(float) {
|
|
const writer = this.writer;
|
|
writer.u8(44);
|
|
switch (float) {
|
|
case Infinity:
|
|
writer.u8u16(105, (110 << 8) |
|
|
102);
|
|
break;
|
|
case -Infinity:
|
|
writer.u32((45 * 0x1000000 +
|
|
105 * 0x10000 +
|
|
(110 << 8)) |
|
|
102);
|
|
break;
|
|
default:
|
|
if (float !== float)
|
|
writer.u8u16(110, (97 << 8) |
|
|
110);
|
|
else
|
|
writer.ascii(float + '');
|
|
break;
|
|
}
|
|
writer.u16(3338);
|
|
}
|
|
writeBin(buf) {
|
|
const writer = this.writer;
|
|
const length = buf.length;
|
|
writer.u8(36);
|
|
this.writeLength(length);
|
|
writer.u16(3338);
|
|
writer.buf(buf, length);
|
|
writer.u16(3338);
|
|
}
|
|
writeBinHdr(length) {
|
|
throw new Error('Not implemented');
|
|
}
|
|
writeStr(str) {
|
|
const length = str.length;
|
|
if (length < 64 && !REG_RN.test(str))
|
|
this.writeSimpleStr(str);
|
|
else
|
|
this.writeVerbatimStr('txt', str);
|
|
}
|
|
writeStrHdr(length) {
|
|
throw new Error('Not implemented');
|
|
}
|
|
writeSimpleStr(str) {
|
|
const writer = this.writer;
|
|
writer.u8(43);
|
|
writer.ensureCapacity(str.length << 2);
|
|
writer.utf8(str);
|
|
writer.u16(3338);
|
|
}
|
|
writeSimpleStrAscii(str) {
|
|
const writer = this.writer;
|
|
writer.u8(43);
|
|
writer.ascii(str);
|
|
writer.u16(3338);
|
|
}
|
|
writeBulkStr(str) {
|
|
const writer = this.writer;
|
|
const size = (0, utf8_1.utf8Size)(str);
|
|
writer.u8(36);
|
|
this.writeLength(size);
|
|
writer.u16(3338);
|
|
writer.ensureCapacity(size);
|
|
writer.utf8(str);
|
|
writer.u16(3338);
|
|
}
|
|
writeBulkStrAscii(str) {
|
|
const writer = this.writer;
|
|
writer.u8(36);
|
|
this.writeLength(str.length);
|
|
writer.u16(3338);
|
|
writer.ascii(str);
|
|
writer.u16(3338);
|
|
}
|
|
writeAsciiStr(str) {
|
|
const isSimple = !REG_RN.test(str);
|
|
if (isSimple)
|
|
this.writeSimpleStr(str);
|
|
else
|
|
this.writeBulkStrAscii(str);
|
|
}
|
|
writeVerbatimStr(encoding, str) {
|
|
const writer = this.writer;
|
|
const size = (0, utf8_1.utf8Size)(str);
|
|
writer.u8(61);
|
|
this.writeLength(size + 4);
|
|
writer.u16(3338);
|
|
writer.u32(encoding.charCodeAt(0) * 0x1000000 +
|
|
(encoding.charCodeAt(1) << 16) +
|
|
(encoding.charCodeAt(2) << 8) +
|
|
58);
|
|
writer.ensureCapacity(size);
|
|
writer.utf8(str);
|
|
writer.u16(3338);
|
|
}
|
|
writeErr(str) {
|
|
if (str.length < 64 && !REG_RN.test(str))
|
|
this.writeSimpleErr(str);
|
|
else
|
|
this.writeBulkErr(str);
|
|
}
|
|
writeSimpleErr(str) {
|
|
const writer = this.writer;
|
|
writer.u8(45);
|
|
writer.ensureCapacity(str.length << 2);
|
|
writer.utf8(str);
|
|
writer.u16(3338);
|
|
}
|
|
writeBulkErr(str) {
|
|
const writer = this.writer;
|
|
const size = (0, utf8_1.utf8Size)(str);
|
|
writer.u8(33);
|
|
this.writeLength(size);
|
|
writer.u16(3338);
|
|
writer.ensureCapacity(size);
|
|
writer.utf8(str);
|
|
writer.u16(3338);
|
|
}
|
|
writeArr(arr) {
|
|
const writer = this.writer;
|
|
const length = arr.length;
|
|
writer.u8(42);
|
|
this.writeLength(length);
|
|
writer.u16(3338);
|
|
for (let i = 0; i < length; i++)
|
|
this.writeAny(arr[i]);
|
|
}
|
|
writeArrHdr(length) {
|
|
const writer = this.writer;
|
|
writer.u8(42);
|
|
this.writeLength(length);
|
|
writer.u16(3338);
|
|
}
|
|
writeObj(obj) {
|
|
const writer = this.writer;
|
|
const keys = Object.keys(obj);
|
|
const length = keys.length;
|
|
writer.u8(37);
|
|
this.writeLength(length);
|
|
writer.u16(3338);
|
|
for (let i = 0; i < length; i++) {
|
|
const key = keys[i];
|
|
this.writeStr(key);
|
|
this.writeAny(obj[key]);
|
|
}
|
|
}
|
|
writeObjHdr(length) {
|
|
const writer = this.writer;
|
|
writer.u8(37);
|
|
this.writeLength(length);
|
|
writer.u16(3338);
|
|
}
|
|
writeAttr(obj) {
|
|
const writer = this.writer;
|
|
const keys = Object.keys(obj);
|
|
const length = keys.length;
|
|
writer.u8(124);
|
|
this.writeLength(length);
|
|
writer.u16(3338);
|
|
for (let i = 0; i < length; i++) {
|
|
const key = keys[i];
|
|
this.writeStr(key);
|
|
this.writeAny(obj[key]);
|
|
}
|
|
}
|
|
writeSet(set) {
|
|
const writer = this.writer;
|
|
const length = set.size;
|
|
writer.u8(126);
|
|
this.writeLength(length);
|
|
writer.u16(3338);
|
|
for (let i = 0; i < length; i++)
|
|
set.forEach((value) => this.writeAny(value));
|
|
}
|
|
writePush(elements) {
|
|
const writer = this.writer;
|
|
const length = elements.length;
|
|
writer.u8(62);
|
|
this.writeLength(length);
|
|
writer.u16(3338);
|
|
for (let i = 0; i < length; i++)
|
|
this.writeAny(elements[i]);
|
|
}
|
|
writeUnknown(value) {
|
|
this.writeNull();
|
|
}
|
|
writeUndef() {
|
|
this.writeNull();
|
|
}
|
|
writeRn() {
|
|
this.writer.u16(3338);
|
|
}
|
|
writeStartStr() {
|
|
this.writer.u32(36 * 0x1000000 +
|
|
(63 << 16) +
|
|
3338);
|
|
}
|
|
writeStrChunk(str) {
|
|
const writer = this.writer;
|
|
writer.u8(59);
|
|
const size = (0, utf8_1.utf8Size)(str);
|
|
this.writeLength(size);
|
|
writer.u16(3338);
|
|
writer.ensureCapacity(size);
|
|
writer.utf8(str);
|
|
writer.u16(3338);
|
|
}
|
|
writeEndStr() {
|
|
this.writer.u32(59 * 0x1000000 +
|
|
(48 << 16) +
|
|
3338);
|
|
}
|
|
writeStartBin() {
|
|
this.writer.u32(36 * 0x1000000 +
|
|
(63 << 16) +
|
|
3338);
|
|
}
|
|
writeBinChunk(buf) {
|
|
const writer = this.writer;
|
|
const length = buf.length;
|
|
writer.u8(59);
|
|
this.writeLength(length);
|
|
writer.u16(3338);
|
|
writer.buf(buf, length);
|
|
writer.u16(3338);
|
|
}
|
|
writeEndBin() {
|
|
this.writer.u32(59 * 0x1000000 +
|
|
(48 << 16) +
|
|
3338);
|
|
}
|
|
writeStartArr() {
|
|
this.writer.u32(42 * 0x1000000 +
|
|
(63 << 16) +
|
|
3338);
|
|
}
|
|
writeArrChunk(item) {
|
|
this.writeAny(item);
|
|
}
|
|
writeEndArr() {
|
|
this.writer.u8u16(46, 3338);
|
|
}
|
|
writeStartObj() {
|
|
this.writer.u32(37 * 0x1000000 +
|
|
(63 << 16) +
|
|
3338);
|
|
}
|
|
writeObjChunk(key, value) {
|
|
this.writeStr(key);
|
|
this.writeAny(value);
|
|
}
|
|
writeEndObj() {
|
|
this.writer.u8u16(46, 3338);
|
|
}
|
|
}
|
|
exports.RespEncoder = RespEncoder;
|
|
//# sourceMappingURL=RespEncoder.js.map
|