Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[fix] Correctly specify the amount of bytes that need to be queued

[api] Added missing Parser#reset method
[test] Added more test
  • Loading branch information...
commit 3e2ee442b858c0edbb067d2b5b92515f1ec4dd71 1 parent d9db804
@3rd-Eden authored
Showing with 78 additions and 19 deletions.
  1. +29 −18 index.js
  2. +49 −1 test/api.test.js
View
47 index.js
@@ -98,6 +98,17 @@ Parser.prototype.flag = function flag(int, parser) {
if ('function' !== typeof parser) throw new Error('The parser should be a function');
this.flags[int.toString()] = parser;
+ return this;
+};
+
+/**
+ * Reset the internal back to their original values.
+ *
+ * @api public
+ */
+Parser.prototype.reset = function reset() {
+ this.expecting = 0;
+ this.queue = '';
};
/**
@@ -327,13 +338,13 @@ Parser.prototype.parse = function parse(bytes) {
// get the char count and not the actual bytes. Pure Buffer parsing
// might be an option for some people, but it's a lot of switching
// between C++ calls vs regular optimized JavaScript shizzle.
- var start = i // Store our starting point, so we can reset the cursor
- , hascas // Do we have a CAS response
- , value // Stored the value buffer
- , bytes // The amount of bytes
- , flags // The flags that were stored with the value
- , key // Stores key
- , cas; // Stores the CAS value
+ var start = i // Store our starting point, so we can reset the cursor
+ , hascas // Do we have a CAS response
+ , value // Stored the value buffer
+ , bytes // The amount of bytes
+ , flags // The flags that were stored with the value
+ , key // Stores key
+ , cas; // Stores the CAS value
// @TODO length folding just like we do in #write
// @TODO test inline var statement vs outside loop var statement
@@ -368,17 +379,6 @@ Parser.prototype.parse = function parse(bytes) {
i += length;
bytesRemaining -= length;
- // Now that we know how much bytes we should expect to have all the
- // content or if we need to wait and buffer more.
- bytes = +bytes;
- if (bytes >= bytesRemaining) {
- // Reset the cursor to the start of the command so the parsed data is
- // removed from the queue when we leave the loop.
- i = start;
- this.expecting = bytes;
- break;
- }
-
// The CAS value is optionally.
if (hascas) {
cas = data.slice(i, rn);
@@ -391,6 +391,17 @@ Parser.prototype.parse = function parse(bytes) {
bytesRemaining -= 1;
}
+ // Now that we know how much bytes we should expect to have all the
+ // content or if we need to wait and buffer more.
+ bytes = +bytes;
+ if (bytes >= bytesRemaining) {
+ // Reset the cursor to the start of the command so the parsed data is
+ // removed from the queue when we leave the loop.
+ this.expecting = bytes + Buffer.byteLength(data.slice(start, i)) + 2;
+ i = start;
+ break;
+ }
+
// Because we are working with binary data here, we need to allocate
// a new buffer, so we can properly slice the data from the string as
// JavaScript doesn't support String#slice that is binary/multi byte aware
View
50 test/api.test.js
@@ -56,7 +56,7 @@ describe('memcached-stream', function () {
expect(memcached.flag.bind(memcached, 2)).to.not.throw(/unsigned/);
});
- it('only only accepts functions as parsers', function () {
+ it('only accepts functions as parsers', function () {
var memcached = new Parser();
expect(memcached.flag.bind(memcached, 1, 1)).to.throw(/function/);
@@ -132,6 +132,54 @@ describe('memcached-stream', function () {
memcached.write('VALUE f 2 26\r\n{"foo":"bar","bar":121313}\r\n');
});
+
+ it('wants to buffer more data if the queue doesnt contain \\r\\n', function (done) {
+ var memcached = new Parser();
+
+ expect(memcached.expecting).to.equal(0);
+ memcached.write('END');
+
+ expect(memcached.expecting).to.equal(5);
+
+ memcached.on('response', function response(command) {
+ expect(command).to.equal('END');
+ expect(memcached.expecting).to.equal(0);
+
+ setTimeout(function timeout() {
+ expect(memcached.queue).to.equal('');
+ done();
+ }, 10);
+ });
+
+ memcached.write('\r\n');
+ });
+
+ it('should buffer on partial VALUE responses', function (done) {
+ var memcached = new Parser()
+ , data = 'VALUE füübar 1 60 9\r\nпривет мир, '
+ , leftover = 'Memcached и nodejs для победы\r\n';
+
+ memcached.write(data);
+ expect(memcached.queue).to.equal(data);
+ expect(memcached.expecting).to.equal(85);
+
+ memcached.on('response', function (command, value, flags, cas, key) {
+ expect(command).to.equal('VALUE');
+ expect(value).to.equal('привет мир, Memcached и nodejs для победы');
+ expect(flags).to.equal('1');
+ expect(cas).to.equal('9');
+ expect(key).to.equal('füübar');
+
+ // should clear the cache
+ process.nextTick(function () {
+ expect(memcached.queue).to.equal('');
+
+ done();
+ });
+ });
+
+ memcached.write(leftover);
+ });
});
});
});
Please sign in to comment.
Something went wrong with that request. Please try again.