diff --git a/src/index-minimal.js b/src/index-minimal.js index 9bc051bd8..1f4aaea6a 100644 --- a/src/index-minimal.js +++ b/src/index-minimal.js @@ -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(); diff --git a/src/reader.js b/src/reader.js index 110cd7182..1b6ae13f8 100644 --- a/src/reader.js +++ b/src/reader.js @@ -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, { diff --git a/src/reader_buffer.js b/src/reader_buffer.js index 95189014f..361a94021 100644 --- a/src/reader_buffer.js +++ b/src/reader_buffer.js @@ -24,9 +24,12 @@ 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 @@ -42,3 +45,5 @@ BufferReader.prototype.string = function read_string_buffer() { * @function * @returns {Buffer} Value read */ + +BufferReader._configure(); diff --git a/src/writer.js b/src/writer.js index f77d83c54..cc84a00e2 100644 --- a/src/writer.js +++ b/src/writer.js @@ -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(); }; diff --git a/src/writer_buffer.js b/src/writer_buffer.js index 55c479ce6..ab4284ffd 100644 --- a/src/writer_buffer.js +++ b/src/writer_buffer.js @@ -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; -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 + 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 + 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; }; @@ -65,7 +64,7 @@ function writeStringBuffer(val, buf, 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(); diff --git a/tests/comp_bytes.js b/tests/comp_bytes.js new file mode 100644 index 000000000..ab088ecf3 --- /dev/null +++ b/tests/comp_bytes.js @@ -0,0 +1,74 @@ +var tape = require("tape"); + +class CustomBuffer extends Buffer { + static toCustom(b) { + b._isCustom = true; + return b; + } + + static isCustom(b) { + return !!b._isCustom; + } + + static from(...args) { + return CustomBuffer.toCustom(Buffer.from(...args)); + } + + static alloc(...args) { + return CustomBuffer.toCustom(Buffer.alloc(...args)); + } + + static allocUnsafe(...args) { + return CustomBuffer.toCustom(Buffer.allocUnsafe(...args)); + } + + static allocUnsafeSlow(...args) { + return CustomBuffer.toCustom(Buffer.allocUnsafeSlow(...args)); + } + + slice(...args) { + return CustomBuffer.toCustom(super.slice(...args)); + } +} + +tape.test("configure a custom encoder/decoder for bytes", function(test) { + + var protobuf = require(".."); + 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: Buffer.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(); + +});