You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
Support for multiple reply parsers including hiredis.
Several parsing bugs fixed in JavaScript. Some new config options that need to be better documented.
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
/*global Buffer require exports console setTimeout */
|
||||
|
||||
var events = require("events"),
|
||||
util = require("../util").util;
|
||||
|
||||
exports.debug_mode = false;
|
||||
exports.name = "javascript";
|
||||
|
||||
function RedisReplyParser(options) {
|
||||
this.name = exports.name;
|
||||
this.options = options || {};
|
||||
this.return_buffers = this.options.return_buffers;
|
||||
if (this.return_buffers == undefined) this.return_buffers = true;
|
||||
this.reset();
|
||||
events.EventEmitter.call(this);
|
||||
}
|
||||
@@ -12,8 +16,6 @@ function RedisReplyParser(options) {
|
||||
util.inherits(RedisReplyParser, events.EventEmitter);
|
||||
|
||||
exports.Parser = RedisReplyParser;
|
||||
exports.debug_mode = false;
|
||||
exports.type = "javascript";
|
||||
|
||||
// Buffer.toString() is quite slow for small strings
|
||||
function small_toString(buf) {
|
||||
@@ -39,13 +41,18 @@ RedisReplyParser.prototype.reset = function () {
|
||||
this.multi_bulk_nested_replies = null;
|
||||
};
|
||||
|
||||
RedisReplyParser.prototype.parser_error = function (message) {
|
||||
this.emit("error", message);
|
||||
this.reset();
|
||||
};
|
||||
|
||||
RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
var pos = 0, bd_tmp, bd_str, i, il;
|
||||
//, state_times = {}, start_execute = new Date(), start_switch, end_switch, old_state;
|
||||
//start_switch = new Date();
|
||||
|
||||
while (pos < incoming_buf.length) {
|
||||
// old_state = this.state;
|
||||
// old_state = this.state;
|
||||
// console.log("execute: " + this.state + ", " + pos + "/" + incoming_buf.length + ", " + String.fromCharCode(incoming_buf[pos]));
|
||||
|
||||
switch (this.state) {
|
||||
@@ -137,11 +144,11 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
this.send_reply(null);
|
||||
this.multi_bulk_length = 0;
|
||||
} else if (this.multi_bulk_length === 0) {
|
||||
this.multi_bulk_replies = null;
|
||||
this.send_reply([]);
|
||||
}
|
||||
} else {
|
||||
this.emit("error", new Error("didn't see LF after NL reading multi bulk count"));
|
||||
this.reset();
|
||||
this.parser_error(new Error("didn't see LF after NL reading multi bulk count"));
|
||||
return;
|
||||
}
|
||||
pos += 1;
|
||||
@@ -171,13 +178,11 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
console.log("Growing return_buffer from " + this.return_buffer.length + " to " + this.bulk_length);
|
||||
}
|
||||
this.return_buffer = new Buffer(this.bulk_length);
|
||||
// home the old one gets cleaned up somehow
|
||||
}
|
||||
this.return_buffer.end = 0;
|
||||
}
|
||||
} else {
|
||||
this.emit("error", new Error("didn't see LF after NL while reading bulk length"));
|
||||
this.reset();
|
||||
this.parser_error(new Error("didn't see LF after NL while reading bulk length"));
|
||||
return;
|
||||
}
|
||||
pos += 1;
|
||||
@@ -186,10 +191,9 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
||||
this.return_buffer.end += 1;
|
||||
pos += 1;
|
||||
// TODO - should be faster to use Bufer.copy() here, especially if the response is large.
|
||||
// However, when the response is small, Buffer.copy() seems a lot slower. Computers are hard.
|
||||
if (this.return_buffer.end === this.bulk_length) {
|
||||
bd_tmp = new Buffer(this.bulk_length);
|
||||
// When the response is small, Buffer.copy() is a lot slower.
|
||||
if (this.bulk_length > 10) {
|
||||
this.return_buffer.copy(bd_tmp, 0, 0, this.bulk_length);
|
||||
} else {
|
||||
@@ -206,8 +210,7 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
this.state = "final lf";
|
||||
pos += 1;
|
||||
} else {
|
||||
this.emit("error", new Error("saw " + incoming_buf[pos] + " when expecting final CR"));
|
||||
this.reset();
|
||||
this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final CR"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -216,13 +219,12 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
this.state = "type";
|
||||
pos += 1;
|
||||
} else {
|
||||
this.emit("error", new Error("saw " + incoming_buf[pos] + " when expecting final LF"));
|
||||
this.reset();
|
||||
this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final LF"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error("invalid state " + this.state);
|
||||
this.parser_error(new Error("invalid state " + this.state));
|
||||
}
|
||||
// end_switch = new Date();
|
||||
// if (state_times[old_state] === undefined) {
|
||||
@@ -248,14 +250,23 @@ RedisReplyParser.prototype.send_error = function (reply) {
|
||||
|
||||
RedisReplyParser.prototype.send_reply = function (reply) {
|
||||
if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) {
|
||||
if (!this.return_buffers && Buffer.isBuffer(reply)) {
|
||||
this.add_multi_bulk_reply(reply.toString("utf8"));
|
||||
if (!this.options.return_buffers && Buffer.isBuffer(reply)) {
|
||||
if (reply.end > 10) {
|
||||
this.add_multi_bulk_reply(reply.toString());
|
||||
} else {
|
||||
this.add_multi_bulk_reply(small_toString(reply));
|
||||
}
|
||||
} else {
|
||||
this.add_multi_bulk_reply(reply);
|
||||
}
|
||||
} else {
|
||||
if (!this.return_buffers && Buffer.isBuffer(reply)) {
|
||||
this.emit("reply", reply.toString("utf8"));
|
||||
if (!this.options.return_buffers && Buffer.isBuffer(reply)) {
|
||||
console.log("converting buffer to string of len " + reply.end + ", " + util.inspect(reply));
|
||||
if (reply.length > 10) {
|
||||
this.emit("reply", reply.toString());
|
||||
} else {
|
||||
this.emit("reply", small_toString(reply));
|
||||
}
|
||||
} else {
|
||||
this.emit("reply", reply);
|
||||
}
|
||||
@@ -265,7 +276,6 @@ RedisReplyParser.prototype.send_reply = function (reply) {
|
||||
RedisReplyParser.prototype.add_multi_bulk_reply = function (reply) {
|
||||
if (this.multi_bulk_replies) {
|
||||
this.multi_bulk_replies.push(reply);
|
||||
// use "less than" here because a nil mb reply claims "0 length", but we need 1 slot to hold it
|
||||
if (this.multi_bulk_replies.length < this.multi_bulk_length) {
|
||||
return;
|
||||
}
|
||||
@@ -288,4 +298,3 @@ RedisReplyParser.prototype.add_multi_bulk_reply = function (reply) {
|
||||
this.multi_bulk_replies = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user