Add support for buffer configuration. (#1257)

* Added support for buffer configuration.

* Fixed tests for node 4.

* Fixed deprecated Buffer methods.
This commit is contained in:
Martín Acosta 2019-11-21 13:53:53 -03:00 committed by Alexander Fenster
parent 4d490eb1bf
commit 5f2f62bcfd
6 changed files with 160 additions and 51 deletions

View File

@ -27,10 +27,10 @@ protobuf.configure = configure;
* @returns {undefined}
*/
function configure() {
protobuf.Reader._configure(protobuf.BufferReader);
protobuf.util._configure();
protobuf.Writer._configure(protobuf.BufferWriter);
protobuf.Reader._configure(protobuf.BufferReader);
}
// Set up buffer utility according to the environment
protobuf.Writer._configure(protobuf.BufferWriter);
configure();

View File

@ -53,6 +53,20 @@ var create_array = typeof Uint8Array !== "undefined"
throw Error("illegal buffer");
};
var create = function create() {
return util.Buffer
? function create_buffer_setup(buffer) {
return (Reader.create = function create_buffer(buffer) {
return util.Buffer.isBuffer(buffer)
? new BufferReader(buffer)
/* istanbul ignore next */
: create_array(buffer);
})(buffer);
}
/* istanbul ignore next */
: create_array;
};
/**
* Creates a new reader using the specified buffer.
* @function
@ -60,17 +74,7 @@ var create_array = typeof Uint8Array !== "undefined"
* @returns {Reader|BufferReader} A {@link BufferReader} if `buffer` is a Buffer, otherwise a {@link Reader}
* @throws {Error} If `buffer` is not a valid buffer
*/
Reader.create = util.Buffer
? function create_buffer_setup(buffer) {
return (Reader.create = function create_buffer(buffer) {
return util.Buffer.isBuffer(buffer)
? new BufferReader(buffer)
/* istanbul ignore next */
: create_array(buffer);
})(buffer);
}
/* istanbul ignore next */
: create_array;
Reader.create = create();
Reader.prototype._slice = util.Array.prototype.subarray || /* istanbul ignore next */ util.Array.prototype.slice;
@ -377,6 +381,8 @@ Reader.prototype.skipType = function(wireType) {
Reader._configure = function(BufferReader_) {
BufferReader = BufferReader_;
Reader.create = create();
BufferReader._configure();
var fn = util.Long ? "toLong" : /* istanbul ignore next */ "toNumber";
util.merge(Reader.prototype, {

View File

@ -24,16 +24,21 @@ function BufferReader(buffer) {
*/
}
/* istanbul ignore else */
if (util.Buffer)
BufferReader.prototype._slice = util.Buffer.prototype.slice;
BufferReader._configure = function () {
/* istanbul ignore else */
if (util.Buffer)
BufferReader.prototype._slice = util.Buffer.prototype.slice;
};
/**
* @override
*/
BufferReader.prototype.string = function read_string_buffer() {
var len = this.uint32(); // modifies pos
return this.buf.utf8Slice(this.pos, this.pos = Math.min(this.pos + len, this.len));
return this.buf.utf8Slice
? this.buf.utf8Slice(this.pos, this.pos = Math.min(this.pos + len, this.len))
: this.buf.toString('utf-8', this.pos, this.pos = Math.min(this.pos + len, this.len))
};
/**
@ -42,3 +47,5 @@ BufferReader.prototype.string = function read_string_buffer() {
* @function
* @returns {Buffer} Value read
*/
BufferReader._configure();

View File

@ -121,21 +121,25 @@ function Writer() {
// part is just a linked list walk calling operations with already prepared values.
}
var create = function create() {
return util.Buffer
? function create_buffer_setup() {
return (Writer.create = function create_buffer() {
return new BufferWriter();
})();
}
/* istanbul ignore next */
: function create_array() {
return new Writer();
};
};
/**
* Creates a new writer.
* @function
* @returns {BufferWriter|Writer} A {@link BufferWriter} when Buffers are supported, otherwise a {@link Writer}
*/
Writer.create = util.Buffer
? function create_buffer_setup() {
return (Writer.create = function create_buffer() {
return new BufferWriter();
})();
}
/* istanbul ignore next */
: function create_array() {
return new Writer();
};
Writer.create = create();
/**
* Allocates a buffer of the specified size.
@ -456,4 +460,6 @@ Writer.prototype.finish = function finish() {
Writer._configure = function(BufferWriter_) {
BufferWriter = BufferWriter_;
Writer.create = create();
BufferWriter._configure();
};

View File

@ -7,8 +7,6 @@ var Writer = require("./writer");
var util = require("./util/minimal");
var Buffer = util.Buffer;
/**
* Constructs a new buffer writer instance.
* @classdesc Wire format writer using node buffers.
@ -19,27 +17,28 @@ function BufferWriter() {
Writer.call(this);
}
/**
* Allocates a buffer of the specified size.
* @param {number} size Buffer size
* @returns {Buffer} Buffer
*/
BufferWriter.alloc = function alloc_buffer(size) {
return (BufferWriter.alloc = util._Buffer_allocUnsafe)(size);
BufferWriter._configure = function () {
/**
* Allocates a buffer of the specified size.
* @param {number} size Buffer size
* @returns {Buffer} Buffer
*/
BufferWriter.alloc = util._Buffer_allocUnsafe;
BufferWriter.writeBytesBuffer = util.Buffer && util.Buffer.prototype instanceof Uint8Array && util.Buffer.prototype.set.name === "set"
? function writeBytesBuffer_set(val, buf, pos) {
buf.set(val, pos); // faster than copy (requires node >= 4 where Buffers extend Uint8Array and set is properly inherited)
// also works for plain array values
}
/* istanbul ignore next */
: function writeBytesBuffer_copy(val, buf, pos) {
if (val.copy) // Buffer values
val.copy(buf, pos, 0, val.length);
else for (var i = 0; i < val.length;) // plain array values
buf[pos++] = val[i++];
};
};
var writeBytesBuffer = Buffer && Buffer.prototype instanceof Uint8Array && Buffer.prototype.set.name === "set"
? function writeBytesBuffer_set(val, buf, pos) {
buf.set(val, pos); // faster than copy (requires node >= 4 where Buffers extend Uint8Array and set is properly inherited)
// also works for plain array values
}
/* istanbul ignore next */
: function writeBytesBuffer_copy(val, buf, pos) {
if (val.copy) // Buffer values
val.copy(buf, pos, 0, val.length);
else for (var i = 0; i < val.length;) // plain array values
buf[pos++] = val[i++];
};
/**
* @override
@ -50,7 +49,7 @@ BufferWriter.prototype.bytes = function write_bytes_buffer(value) {
var len = value.length >>> 0;
this.uint32(len);
if (len)
this._push(writeBytesBuffer, len, value);
this._push(BufferWriter.writeBytesBuffer, len, value);
return this;
};
@ -58,14 +57,14 @@ function writeStringBuffer(val, buf, pos) {
if (val.length < 40) // plain js is faster for short strings (probably due to redundant assertions)
util.utf8.write(val, buf, pos);
else
buf.utf8Write(val, pos);
buf.utf8Write ? buf.utf8Write(val, pos) : buf.write(val, pos);
}
/**
* @override
*/
BufferWriter.prototype.string = function write_string_buffer(value) {
var len = Buffer.byteLength(value);
var len = util.Buffer.byteLength(value);
this.uint32(len);
if (len)
this._push(writeStringBuffer, len, value);
@ -79,3 +78,5 @@ BufferWriter.prototype.string = function write_string_buffer(value) {
* @function
* @returns {Buffer} Finished buffer
*/
BufferWriter._configure();

89
tests/comp_bytes.js Normal file
View File

@ -0,0 +1,89 @@
var tape = require("tape");
var protobuf = require("..");
var oldBufferImpl = Buffer.alloc === undefined;
// extends Buffer
(CustomBuffer.prototype = Object.create(Buffer.prototype)).constructor = CustomBuffer;
function CustomBuffer(arg, encodingOrOffset, length) {
Buffer.call(this, arg, encodingOrOffset, length);
CustomBuffer.toCustom(this);
}
CustomBuffer.isBuffer = Buffer.isBuffer.bind(Buffer);
CustomBuffer.toCustom = function (b) {
b._isCustom = true;
return b;
}
CustomBuffer.isCustom = function (b) {
return !!b._isCustom;
}
CustomBuffer.from = function (valueOf, encodingOrOffset, length) {
return CustomBuffer.toCustom(oldBufferImpl
? new Buffer(valueOf, encodingOrOffset, length)
: Buffer.from(valueOf, encodingOrOffset, length)
);
}
CustomBuffer.alloc = function (size, fill, encoding) {
return CustomBuffer.toCustom(oldBufferImpl
? new Buffer(size, fill, encoding)
: Buffer.alloc(size, fill, encoding)
);
}
CustomBuffer.allocUnsafe = function (size) {
return CustomBuffer.toCustom(oldBufferImpl
? new Buffer(size)
: Buffer.allocUnsafe(size)
);
}
CustomBuffer.prototype.slice = function (start, end) {
return CustomBuffer.toCustom(this.slice(start, end));
}
tape.test("configure a custom encoder/decoder for bytes", function(test) {
var oldBuffer = protobuf.util.Buffer;
protobuf.util.Buffer = CustomBuffer;
protobuf.configure();
var root = protobuf.Root.fromJSON({
nested: {
test: {
nested: {
Test: {
fields: {
data: {
type: "bytes",
id: 1
}
}
}
}
}
}
});
var Test = root.lookup("test.Test");
var buffer = Test.encode({
data: CustomBuffer.from('some-data')
}).finish();
test.ok(CustomBuffer.isCustom(buffer), "should encode the message with a custom buffer");
var decoded = Test.decode(buffer);
test.ok(CustomBuffer.isCustom(decoded.data), "should decode `data` into a custom buffer");
protobuf.util.Buffer = oldBuffer;
protobuf.configure();
test.end();
});