UNPKG

@jsonjoy.com/json-pack

Version:

High-performance JSON serialization library

408 lines 13.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RespDecoder = void 0; const Reader_1 = require("@jsonjoy.com/buffers/lib/Reader"); const extensions_1 = require("./extensions"); const isUtf8_1 = require("@jsonjoy.com/buffers/lib/utf8/isUtf8"); class RespDecoder { constructor(reader = new Reader_1.Reader()) { this.reader = reader; /** * When set to true, the decoder will attempt to decode RESP Bulk strings * (which are binary strings, i.e. Uint8Array) as UTF-8 strings. If the * string is not valid UTF-8, it will be returned as a Uint8Array. * * You can toggle this setting at any time, before each call to `decode()` * or `read()`, or other methods. */ this.tryUtf8 = false; } read(uint8) { this.reader.reset(uint8); return this.readAny(); } /** @deprecated */ decode(uint8) { this.reader.reset(uint8); return this.readAny(); } // -------------------------------------------------------- Any value reading val() { return this.readAny(); } readAny() { const reader = this.reader; const type = reader.u8(); switch (type) { case 58 /* RESP.INT */: return this.readInt(); case 44 /* RESP.FLOAT */: return this.readFloat(); case 43 /* RESP.STR_SIMPLE */: return this.readStrSimple(); case 36 /* RESP.STR_BULK */: return this.readStrBulk(); case 35 /* RESP.BOOL */: return this.readBool(); case 95 /* RESP.NULL */: return reader.skip(2), null; case 37 /* RESP.OBJ */: return this.readObj(); case 42 /* RESP.ARR */: return this.readArr(); case 61 /* RESP.STR_VERBATIM */: return this.readStrVerbatim(); case 62 /* RESP.PUSH */: return new extensions_1.RespPush(this.readArr() || []); case 40 /* RESP.BIG */: return this.readBigint(); case 126 /* RESP.SET */: return this.readSet(); case 45 /* RESP.ERR_SIMPLE */: return this.readErrSimple(); case 33 /* RESP.ERR_BULK */: return this.readErrBulk(); case 124 /* RESP.ATTR */: return new extensions_1.RespAttributes(this.readObj()); } throw new Error('UNKNOWN_TYPE'); } readLength() { const reader = this.reader; let number = 0; while (true) { const c = reader.u8(); if (c === 13 /* RESP.R */) return reader.skip(1), number; number = number * 10 + (c - 48); } } readCmd() { const reader = this.reader; const type = reader.u8(); if (type !== 42 /* RESP.ARR */) throw new Error('INVALID_COMMAND'); const c = reader.peak(); if (c === 45 /* RESP.MINUS */) throw new Error('INVALID_COMMAND'); const length = this.readLength(); if (length === 0) throw new Error('INVALID_COMMAND'); const cmd = this.readAsciiAsStrBulk().toUpperCase(); const args = [cmd]; this.tryUtf8 = false; for (let i = 1; i < length; i++) { const type = reader.u8(); if (type !== 36 /* RESP.STR_BULK */) throw new Error('INVALID_COMMAND'); args.push(this.readStrBulk()); } return args; } // ---------------------------------------------------------- Boolean reading readBool() { const reader = this.reader; const c = reader.u8(); reader.skip(2); // Skip "\r\n". return c === 116; // t } // ----------------------------------------------------------- Number reading readInt() { const reader = this.reader; let negative = false; let c = reader.u8(); let number = 0; if (c === 45 /* RESP.MINUS */) { negative = true; } else if (c !== 43 /* RESP.PLUS */) number = c - 48; while (true) { c = reader.u8(); if (c === 13 /* RESP.R */) { reader.skip(1); // Skip "\n". return negative ? -number : number; } number = number * 10 + (c - 48); } } readFloat() { const reader = this.reader; const x = reader.x; while (true) { const c = reader.u8(); if (c !== 13 /* RESP.R */) continue; const length = reader.x - x - 1; reader.x = x; const str = reader.ascii(length); switch (length) { case 3: switch (str) { case 'inf': return reader.skip(2), Infinity; case 'nan': return reader.skip(2), NaN; } break; case 4: if (str === '-inf') { return reader.skip(2), -Infinity; } break; } reader.skip(2); // Skip "\n". return Number(str); } } readBigint() { const reader = this.reader; const x = reader.x; while (true) { const c = reader.u8(); if (c !== 13 /* RESP.R */) continue; const length = reader.x - x; reader.x = x; const str = reader.ascii(length); reader.skip(1); // Skip "\n". return BigInt(str); } } // ----------------------------------------------------------- String reading readStrSimple() { const reader = this.reader; const x = reader.x; while (true) { const c = reader.u8(); if (c !== 13 /* RESP.R */) continue; const size = reader.x - x - 1; reader.x = x; const str = reader.utf8(size); reader.skip(2); // Skip "\r\n". return str; } } readStrBulk() { const reader = this.reader; if (reader.peak() === 45 /* RESP.MINUS */) { reader.skip(4); // Skip "-1\r\n". return null; } const length = this.readLength(); let res; if (this.tryUtf8 && (0, isUtf8_1.isUtf8)(reader.uint8, reader.x, length)) res = reader.utf8(length); else res = reader.buf(length); reader.skip(2); // Skip "\r\n". return res; } readAsciiAsStrBulk() { const reader = this.reader; reader.skip(1); // Skip "$". const length = this.readLength(); const buf = reader.ascii(length); reader.skip(2); // Skip "\r\n". return buf; } readStrVerbatim() { const reader = this.reader; const length = this.readLength(); const u32 = reader.u32(); const isTxt = u32 === 1954051130; // "txt:" if (isTxt) { const str = reader.utf8(length - 4); reader.skip(2); // Skip "\r\n". return str; } const buf = reader.buf(length - 4); reader.skip(2); // Skip "\r\n". return buf; } // ------------------------------------------------------------ Error reading readErrSimple() { const reader = this.reader; const x = reader.x; while (true) { const c = reader.u8(); if (c !== 13 /* RESP.R */) continue; const size = reader.x - x - 1; reader.x = x; const str = reader.utf8(size); reader.skip(2); // Skip "\r\n". return new Error(str); } } readErrBulk() { const reader = this.reader; const length = this.readLength(); const message = reader.utf8(length); reader.skip(2); // Skip "\r\n". return new Error(message); } // ------------------------------------------------------------ Array reading readArr() { const reader = this.reader; const c = reader.peak(); if (c === 45 /* RESP.MINUS */) { reader.skip(4); // Skip "-1\r\n". return null; } const length = this.readLength(); const arr = []; for (let i = 0; i < length; i++) arr.push(this.readAny()); return arr; } readSet() { const length = this.readLength(); const set = new Set(); for (let i = 0; i < length; i++) set.add(this.readAny()); return set; } // ----------------------------------------------------------- Object reading readObj() { const length = this.readLength(); const obj = {}; for (let i = 0; i < length; i++) { const key = this.readAny() + ''; obj[key] = this.readAny(); } return obj; } // ----------------------------------------------------------------- Skipping skipN(n) { for (let i = 0; i < n; i++) this.skipAny(); } skipAny() { const reader = this.reader; const type = reader.u8(); switch (type) { case 58 /* RESP.INT */: return this.skipInt(); case 44 /* RESP.FLOAT */: return this.skipFloat(); case 43 /* RESP.STR_SIMPLE */: return this.skipStrSimple(); case 36 /* RESP.STR_BULK */: return this.skipStrBulk(); case 35 /* RESP.BOOL */: return this.skipBool(); case 95 /* RESP.NULL */: return reader.skip(2); case 37 /* RESP.OBJ */: return this.skipObj(); case 42 /* RESP.ARR */: return this.skipArr(); case 61 /* RESP.STR_VERBATIM */: return this.skipStrVerbatim(); case 62 /* RESP.PUSH */: return this.skipArr(); case 40 /* RESP.BIG */: return this.skipBigint(); case 126 /* RESP.SET */: return this.skipSet(); case 45 /* RESP.ERR_SIMPLE */: return this.skipErrSimple(); case 33 /* RESP.ERR_BULK */: return this.skipErrBulk(); case 124 /* RESP.ATTR */: return this.skipObj(); } throw new Error('UNKNOWN_TYPE'); } skipBool() { this.reader.skip(3); } skipInt() { const reader = this.reader; while (true) { if (reader.u8() !== 13 /* RESP.R */) continue; reader.skip(1); // Skip "\n". return; } } skipFloat() { const reader = this.reader; while (true) { if (reader.u8() !== 13 /* RESP.R */) continue; reader.skip(1); // Skip "\n". return; } } skipBigint() { const reader = this.reader; while (true) { if (reader.u8() !== 13 /* RESP.R */) continue; reader.skip(1); // Skip "\n". return; } } skipStrSimple() { const reader = this.reader; while (true) { if (reader.u8() !== 13 /* RESP.R */) continue; reader.skip(1); // Skip "\n". return; } } skipStrBulk() { const reader = this.reader; if (reader.peak() === 45 /* RESP.MINUS */) { reader.skip(4); // Skip "-1\r\n". return; } reader.skip(this.readLength() + 2); // Skip "\r\n". } skipStrVerbatim() { const length = this.readLength(); this.reader.skip(length + 2); // Skip "\r\n". } skipErrSimple() { const reader = this.reader; while (true) { if (reader.u8() !== 13 /* RESP.R */) continue; reader.skip(1); // Skip "\n". return; } } skipErrBulk() { const length = this.readLength(); this.reader.skip(length + 2); // Skip "\r\n". } skipArr() { const reader = this.reader; const c = reader.peak(); if (c === 45 /* RESP.MINUS */) { reader.skip(4); // Skip "-1\r\n". return; } const length = this.readLength(); for (let i = 0; i < length; i++) this.skipAny(); } skipSet() { const length = this.readLength(); for (let i = 0; i < length; i++) this.skipAny(); } skipObj() { const length = this.readLength(); for (let i = 0; i < length; i++) { this.skipAny(); this.skipAny(); } } } exports.RespDecoder = RespDecoder; //# sourceMappingURL=RespDecoder.js.map