@litert/redis
Version:
A redis protocol implement for Node.js.
156 lines • 5.12 kB
JavaScript
;
/**
* 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