UNPKG

@litert/redis

Version:

A redis protocol implement for Node.js.

156 lines 5.12 kB
"use strict"; /** * Copyright 2025 Angus.Fenying <fenying@litert.org> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Encoder = void 0; const A = require("./Common"); const E = require("./Errors"); const C = require("./Constants"); var PROTO_DELIMITER = C.PROTO_DELIMITER; var PROTO_NULL = C.PROTO_NULL; var PROTO_DELIMITER_VALUE = C.PROTO_DELIMITER_VALUE; class Encoder { _getStringEncodedLength(val) { const l = Buffer.byteLength(val); return 5 + l + l.toString().length; } _writeString(target, val, pos) { pos += target.write(`$${Buffer.byteLength(val)}`, pos); pos += PROTO_DELIMITER.copy(target, pos); if (typeof val === 'string') { pos += target.write(val, pos); } else { pos += val.copy(target, pos); } pos += PROTO_DELIMITER.copy(target, pos); return pos; } encodeNull() { return PROTO_NULL.subarray(); } encodeCommand(cmd, values) { let length = 3; if (values) { for (let i = 0; i < values.length; i++) { if (typeof values[i] === 'number') { values[i] = values[i].toString(); } } length += (1 + values.length).toString().length; for (const el of values) { length += this._getStringEncodedLength(el); } } else { length += 1; } length += this._getStringEncodedLength(cmd); const ret = Buffer.allocUnsafe(length); let pos = 0; pos += ret.write(`*${values ? values.length + 1 : 1}`, pos); pos += PROTO_DELIMITER.copy(ret, pos); pos = this._writeString(ret, cmd, pos); if (values) { for (const el of values) { pos = this._writeString(ret, el, pos); } } return ret; } encodeString(data) { const ret = Buffer.allocUnsafe(this._getStringEncodedLength(data)); this._writeString(ret, data, 0); return ret; } encodeMessage(data) { if (data.indexOf(PROTO_DELIMITER_VALUE) > -1) { throw new E.E_PROTOCOL_ERROR({ 'message': 'CRLF is forbidden in MESSAGE.' }); } const length = Buffer.byteLength(data); const ret = Buffer.allocUnsafe(length + 3); ret[0] = 43; if (typeof data === 'string') { ret.write(data, 1); } else { data.copy(ret, 1); } PROTO_DELIMITER.copy(ret, length + 1); return ret; } encodeFailure(data) { if (data.indexOf(PROTO_DELIMITER_VALUE) > -1) { throw new E.E_PROTOCOL_ERROR({ 'message': 'CRLF is forbidden in MESSAGE.' }); } const length = Buffer.byteLength(data); const ret = Buffer.allocUnsafe(length + 3); ret[0] = 45; if (typeof data === 'string') { ret.write(data, 1); } else { data.copy(ret, 1); } PROTO_DELIMITER.copy(ret, length + 1); return ret; } encodeInteger(val) { const data = val.toString(); const len = Buffer.byteLength(data); const ret = Buffer.allocUnsafe(3 + len); ret[0] = 58; ret.write(data, 1); PROTO_DELIMITER.copy(ret, len + 1); return ret; } encodeList(data) { const ret = [ Buffer.from(`*${data.length}`), PROTO_DELIMITER ]; for (const item of data) { switch (item[0]) { case A.EDataType.FAILURE: ret.push(this.encodeString(item[1])); break; case A.EDataType.MESSAGE: ret.push(this.encodeMessage(item[1])); break; case A.EDataType.STRING: ret.push(this.encodeString(item[1])); break; case A.EDataType.INTEGER: ret.push(this.encodeInteger(item[1])); break; case A.EDataType.LIST: ret.push(this.encodeList(item[1])); break; case A.EDataType.NULL: ret.push(this.encodeNull()); break; } } return Buffer.concat(ret); } } exports.Encoder = Encoder; exports.default = Encoder; //# sourceMappingURL=Encoder.js.map