diffusion
Version:
Diffusion JavaScript client
156 lines (134 loc) • 4.34 kB
JavaScript
/*eslint valid-jsdoc: "off"*/
function ensureCapacity(bos, min) {
if (min - bos.buffer.length > 0) {
grow(bos, min);
}
}
/**
* Grow a given buffer up to the next minimum capacity (or higher).
*
* @param {BufferOutputStream} bos - The output stream to grow
* @param {Number} minCapacity - The minimum capacity required
* @throws If the new capacity exceeds that with which a Buffer can be created,
* an error will be thrown.
*/
function grow(bos, minCapacity) {
var oldCapacity = bos.buffer.length,
newCapacity = oldCapacity << 1;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
try {
var replacement = new Buffer(newCapacity);
bos.buffer.copy(replacement);
bos.buffer = replacement;
} catch (e) {
throw new Error("Unable to resize BufferOutputStream to " + newCapacity);
}
}
/**
* Wrapper around a single Buffer, providing auto-resizing capabilities.
* <P>
* All write operations will append to the internal buffer.
* <P>
* Loosely inspired by Java's ByteArrayOutputStream.
* @constructor
* @param {number|Buffer} [initial=32]
* - The initial size for the internal Buffer, or buffer to use as source.
*/
function BufferOutputStream(initial) {
if (Buffer.isBuffer(initial)) {
this.buffer = initial;
this.count = initial.length;
} else {
this.buffer = new Buffer((initial || 32));
this.count = 0;
}
}
/**
* Write a single byte.
*
* @param {Number} - The byte to append
*/
BufferOutputStream.prototype.write = function (val) {
ensureCapacity(this, this.count + 1);
this.buffer[this.count++] = val;
};
/**
* Write many bytes.
* <P>
* The contents of the provided buffer will be copied and appended. The full
* length of the buffer will be copied, irrespective of byte content.
*
* @param {Buffer} buffer - The bytes to append.
* @param {Number} [offset=0] - The offset to start copying from the provided buffer
* @param {Number} [length=buffer.length] - The amount of bytes to copy from the provided buffer
*/
BufferOutputStream.prototype.writeMany = function (buffer, offset, length) {
if (length === 0) {
// nothing to write, just bail out here
return;
}
offset = offset || 0;
length = length || buffer.length;
ensureCapacity(this, this.count + length);
buffer.copy(this.buffer, this.count, offset, offset + length);
this.count += length;
};
/**
* Write a String in UTF-8 format.
*
* @param {String} - The string value to be appended.
*/
BufferOutputStream.prototype.writeString = function (val) {
var length = Buffer.byteLength(val);
ensureCapacity(this, this.count + length);
// Strings are encoded as UTF-8 by default
this.buffer.write(val, this.count, length);
this.count += length;
};
/**
* Write a signed 8-bit integer.
* @param {Number} - The number to write
*/
BufferOutputStream.prototype.writeInt8 = function (val) {
ensureCapacity(this, this.count + 1);
this.buffer.writeInt8(val, this.count++);
};
/**
* Write a signed, big-endian 32-bit integer.
* @param {Number} - The number to write
*/
BufferOutputStream.prototype.writeInt32 = function (val) {
ensureCapacity(this, this.count + 4);
this.buffer.writeInt32BE(val, this.count);
this.count += 4;
};
/**
* Write a signed, big-endian 64-bit long.
* @param {Long} - The number to write.
*/
BufferOutputStream.prototype.writeInt64 = function (val) {
ensureCapacity(this, this.count + 8);
this.buffer.writeInt32BE(val.getHighBits(), this.count);
this.buffer.writeInt32BE(val.getLowBits(), this.count + 4);
this.count += 8;
};
/**
* Return the written bytes as a buffer, sized to the last value written.
* <p>
* Any modifications to the returned buffer will be reflected in this OutputStream.
*
* @returns {Buffer} A Buffer containing all the bytes current written to this OutputStream.
*/
BufferOutputStream.prototype.getBuffer = function () {
return this.buffer.slice(0, this.count);
};
/**
* Return written bytes as a base64 encoded string.
* @returns {String} The base64 encoded string
*/
BufferOutputStream.prototype.getBase64 = function () {
return this.getBuffer().toString('base64');
};
module.exports = BufferOutputStream;