"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("./utils"); // The default Buffer size if one is not provided. const DEFAULT_SMARTBUFFER_SIZE = 4096; // The default string encoding to use for reading/writing strings. const DEFAULT_SMARTBUFFER_ENCODING = 'utf8'; class SmartBuffer { /** * Creates a new SmartBuffer instance. * * @param options { SmartBufferOptions } The SmartBufferOptions to apply to this instance. */ constructor(options) { this.length = 0; this._encoding = DEFAULT_SMARTBUFFER_ENCODING; this._writeOffset = 0; this._readOffset = 0; if (SmartBuffer.isSmartBufferOptions(options)) { // Checks for encoding if (options.encoding) { utils_1.checkEncoding(options.encoding); this._encoding = options.encoding; } // Checks for initial size length if (options.size) { if (utils_1.isFiniteInteger(options.size) && options.size > 0) { this._buff = Buffer.allocUnsafe(options.size); } else { throw new Error(utils_1.ERRORS.INVALID_SMARTBUFFER_SIZE); } // Check for initial Buffer } else if (options.buff) { if (Buffer.isBuffer(options.buff)) { this._buff = options.buff; this.length = options.buff.length; } else { throw new Error(utils_1.ERRORS.INVALID_SMARTBUFFER_BUFFER); } } else { this._buff = Buffer.allocUnsafe(DEFAULT_SMARTBUFFER_SIZE); } } else { // If something was passed but it's not a SmartBufferOptions object if (typeof options !== 'undefined') { throw new Error(utils_1.ERRORS.INVALID_SMARTBUFFER_OBJECT); } // Otherwise default to sane options this._buff = Buffer.allocUnsafe(DEFAULT_SMARTBUFFER_SIZE); } } /** * Creates a new SmartBuffer instance with the provided internal Buffer size and optional encoding. * * @param size { Number } The size of the internal Buffer. * @param encoding { String } The BufferEncoding to use for strings. * * @return { SmartBuffer } */ static fromSize(size, encoding) { return new this({ size: size, encoding: encoding }); } /** * Creates a new SmartBuffer instance with the provided Buffer and optional encoding. * * @param buffer { Buffer } The Buffer to use as the internal Buffer value. * @param encoding { String } The BufferEncoding to use for strings. * * @return { SmartBuffer } */ static fromBuffer(buff, encoding) { return new this({ buff: buff, encoding: encoding }); } /** * Creates a new SmartBuffer instance with the provided SmartBufferOptions options. * * @param options { SmartBufferOptions } The options to use when creating the SmartBuffer instance. */ static fromOptions(options) { return new this(options); } /** * Type checking function that determines if an object is a SmartBufferOptions object. */ static isSmartBufferOptions(options) { const castOptions = options; return (castOptions && (castOptions.encoding !== undefined || castOptions.size !== undefined || castOptions.buff !== undefined)); } // Signed integers /** * Reads an Int8 value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readInt8(offset) { return this._readNumberValue(Buffer.prototype.readInt8, 1, offset); } /** * Reads an Int16BE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readInt16BE(offset) { return this._readNumberValue(Buffer.prototype.readInt16BE, 2, offset); } /** * Reads an Int16LE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readInt16LE(offset) { return this._readNumberValue(Buffer.prototype.readInt16LE, 2, offset); } /** * Reads an Int32BE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readInt32BE(offset) { return this._readNumberValue(Buffer.prototype.readInt32BE, 4, offset); } /** * Reads an Int32LE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readInt32LE(offset) { return this._readNumberValue(Buffer.prototype.readInt32LE, 4, offset); } /** * Reads a BigInt64BE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { BigInt } */ readBigInt64BE(offset) { utils_1.bigIntAndBufferInt64Check('readBigInt64BE'); return this._readNumberValue(Buffer.prototype.readBigInt64BE, 8, offset); } /** * Reads a BigInt64LE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { BigInt } */ readBigInt64LE(offset) { utils_1.bigIntAndBufferInt64Check('readBigInt64LE'); return this._readNumberValue(Buffer.prototype.readBigInt64LE, 8, offset); } /** * Writes an Int8 value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeInt8(value, offset) { this._writeNumberValue(Buffer.prototype.writeInt8, 1, value, offset); return this; } /** * Inserts an Int8 value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertInt8(value, offset) { return this._insertNumberValue(Buffer.prototype.writeInt8, 1, value, offset); } /** * Writes an Int16BE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeInt16BE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeInt16BE, 2, value, offset); } /** * Inserts an Int16BE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertInt16BE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeInt16BE, 2, value, offset); } /** * Writes an Int16LE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeInt16LE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeInt16LE, 2, value, offset); } /** * Inserts an Int16LE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertInt16LE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeInt16LE, 2, value, offset); } /** * Writes an Int32BE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeInt32BE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeInt32BE, 4, value, offset); } /** * Inserts an Int32BE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertInt32BE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeInt32BE, 4, value, offset); } /** * Writes an Int32LE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeInt32LE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeInt32LE, 4, value, offset); } /** * Inserts an Int32LE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertInt32LE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeInt32LE, 4, value, offset); } /** * Writes a BigInt64BE value to the current write position (or at optional offset). * * @param value { BigInt } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeBigInt64BE(value, offset) { utils_1.bigIntAndBufferInt64Check('writeBigInt64BE'); return this._writeNumberValue(Buffer.prototype.writeBigInt64BE, 8, value, offset); } /** * Inserts a BigInt64BE value at the given offset value. * * @param value { BigInt } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertBigInt64BE(value, offset) { utils_1.bigIntAndBufferInt64Check('writeBigInt64BE'); return this._insertNumberValue(Buffer.prototype.writeBigInt64BE, 8, value, offset); } /** * Writes a BigInt64LE value to the current write position (or at optional offset). * * @param value { BigInt } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeBigInt64LE(value, offset) { utils_1.bigIntAndBufferInt64Check('writeBigInt64LE'); return this._writeNumberValue(Buffer.prototype.writeBigInt64LE, 8, value, offset); } /** * Inserts a Int64LE value at the given offset value. * * @param value { BigInt } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertBigInt64LE(value, offset) { utils_1.bigIntAndBufferInt64Check('writeBigInt64LE'); return this._insertNumberValue(Buffer.prototype.writeBigInt64LE, 8, value, offset); } // Unsigned Integers /** * Reads an UInt8 value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readUInt8(offset) { return this._readNumberValue(Buffer.prototype.readUInt8, 1, offset); } /** * Reads an UInt16BE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readUInt16BE(offset) { return this._readNumberValue(Buffer.prototype.readUInt16BE, 2, offset); } /** * Reads an UInt16LE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readUInt16LE(offset) { return this._readNumberValue(Buffer.prototype.readUInt16LE, 2, offset); } /** * Reads an UInt32BE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readUInt32BE(offset) { return this._readNumberValue(Buffer.prototype.readUInt32BE, 4, offset); } /** * Reads an UInt32LE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readUInt32LE(offset) { return this._readNumberValue(Buffer.prototype.readUInt32LE, 4, offset); } /** * Reads a BigUInt64BE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { BigInt } */ readBigUInt64BE(offset) { utils_1.bigIntAndBufferInt64Check('readBigUInt64BE'); return this._readNumberValue(Buffer.prototype.readBigUInt64BE, 8, offset); } /** * Reads a BigUInt64LE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { BigInt } */ readBigUInt64LE(offset) { utils_1.bigIntAndBufferInt64Check('readBigUInt64LE'); return this._readNumberValue(Buffer.prototype.readBigUInt64LE, 8, offset); } /** * Writes an UInt8 value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeUInt8(value, offset) { return this._writeNumberValue(Buffer.prototype.writeUInt8, 1, value, offset); } /** * Inserts an UInt8 value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertUInt8(value, offset) { return this._insertNumberValue(Buffer.prototype.writeUInt8, 1, value, offset); } /** * Writes an UInt16BE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeUInt16BE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeUInt16BE, 2, value, offset); } /** * Inserts an UInt16BE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertUInt16BE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeUInt16BE, 2, value, offset); } /** * Writes an UInt16LE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeUInt16LE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeUInt16LE, 2, value, offset); } /** * Inserts an UInt16LE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertUInt16LE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeUInt16LE, 2, value, offset); } /** * Writes an UInt32BE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeUInt32BE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeUInt32BE, 4, value, offset); } /** * Inserts an UInt32BE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertUInt32BE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeUInt32BE, 4, value, offset); } /** * Writes an UInt32LE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeUInt32LE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeUInt32LE, 4, value, offset); } /** * Inserts an UInt32LE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertUInt32LE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeUInt32LE, 4, value, offset); } /** * Writes a BigUInt64BE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeBigUInt64BE(value, offset) { utils_1.bigIntAndBufferInt64Check('writeBigUInt64BE'); return this._writeNumberValue(Buffer.prototype.writeBigUInt64BE, 8, value, offset); } /** * Inserts a BigUInt64BE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertBigUInt64BE(value, offset) { utils_1.bigIntAndBufferInt64Check('writeBigUInt64BE'); return this._insertNumberValue(Buffer.prototype.writeBigUInt64BE, 8, value, offset); } /** * Writes a BigUInt64LE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeBigUInt64LE(value, offset) { utils_1.bigIntAndBufferInt64Check('writeBigUInt64LE'); return this._writeNumberValue(Buffer.prototype.writeBigUInt64LE, 8, value, offset); } /** * Inserts a BigUInt64LE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertBigUInt64LE(value, offset) { utils_1.bigIntAndBufferInt64Check('writeBigUInt64LE'); return this._insertNumberValue(Buffer.prototype.writeBigUInt64LE, 8, value, offset); } // Floating Point /** * Reads an FloatBE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readFloatBE(offset) { return this._readNumberValue(Buffer.prototype.readFloatBE, 4, offset); } /** * Reads an FloatLE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readFloatLE(offset) { return this._readNumberValue(Buffer.prototype.readFloatLE, 4, offset); } /** * Writes a FloatBE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeFloatBE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeFloatBE, 4, value, offset); } /** * Inserts a FloatBE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertFloatBE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeFloatBE, 4, value, offset); } /** * Writes a FloatLE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeFloatLE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeFloatLE, 4, value, offset); } /** * Inserts a FloatLE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertFloatLE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeFloatLE, 4, value, offset); } // Double Floating Point /** * Reads an DoublEBE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readDoubleBE(offset) { return this._readNumberValue(Buffer.prototype.readDoubleBE, 8, offset); } /** * Reads an DoubleLE value from the current read position or an optionally provided offset. * * @param offset { Number } The offset to read data from (optional) * @return { Number } */ readDoubleLE(offset) { return this._readNumberValue(Buffer.prototype.readDoubleLE, 8, offset); } /** * Writes a DoubleBE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeDoubleBE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeDoubleBE, 8, value, offset); } /** * Inserts a DoubleBE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertDoubleBE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeDoubleBE, 8, value, offset); } /** * Writes a DoubleLE value to the current write position (or at optional offset). * * @param value { Number } The value to write. * @param offset { Number } The offset to write the value at. * * @return this */ writeDoubleLE(value, offset) { return this._writeNumberValue(Buffer.prototype.writeDoubleLE, 8, value, offset); } /** * Inserts a DoubleLE value at the given offset value. * * @param value { Number } The value to insert. * @param offset { Number } The offset to insert the value at. * * @return this */ insertDoubleLE(value, offset) { return this._insertNumberValue(Buffer.prototype.writeDoubleLE, 8, value, offset); } // Strings /** * Reads a String from the current read position. * * @param arg1 { Number | String } The number of bytes to read as a String, or the BufferEncoding to use for * the string (Defaults to instance level encoding). * @param encoding { String } The BufferEncoding to use for the string (Defaults to instance level encoding). * * @return { String } */ readString(arg1, encoding) { let lengthVal; // Length provided if (typeof arg1 === 'number') { utils_1.checkLengthValue(arg1); lengthVal = Math.min(arg1, this.length - this._readOffset); } else { encoding = arg1; lengthVal = this.length - this._readOffset; } // Check encoding if (typeof encoding !== 'undefined') { utils_1.checkEncoding(encoding); } const value = this._buff.slice(this._readOffset, this._readOffset + lengthVal).toString(encoding || this._encoding); this._readOffset += lengthVal; return value; } /** * Inserts a String * * @param value { String } The String value to insert. * @param offset { Number } The offset to insert the string at. * @param encoding { String } The BufferEncoding to use for writing strings (defaults to instance encoding). * * @return this */ insertString(value, offset, encoding) { utils_1.checkOffsetValue(offset); return this._handleString(value, true, offset, encoding); } /** * Writes a String * * @param value { String } The String value to write. * @param arg2 { Number | String } The offset to write the string at, or the BufferEncoding to use. * @param encoding { String } The BufferEncoding to use for writing strings (defaults to instance encoding). * * @return this */ writeString(value, arg2, encoding) { return this._handleString(value, false, arg2, encoding); } /** * Reads a null-terminated String from the current read position. * * @param encoding { String } The BufferEncoding to use for the string (Defaults to instance level encoding). * * @return { String } */ readStringNT(encoding) { if (typeof encoding !== 'undefined') { utils_1.checkEncoding(encoding); } // Set null character position to the end SmartBuffer instance. let nullPos = this.length; // Find next null character (if one is not found, default from above is used) for (let i = this._readOffset; i < this.length; i++) { if (this._buff[i] === 0x00) { nullPos = i; break; } } // Read string value const value = this._buff.slice(this._readOffset, nullPos); // Increment internal Buffer read offset this._readOffset = nullPos + 1; return value.toString(encoding || this._encoding); } /** * Inserts a null-terminated String. * * @param value { String } The String value to write. * @param arg2 { Number | String } The offset to write the string to, or the BufferEncoding to use. * @param encoding { String } The BufferEncoding to use for writing strings (defaults to instance encoding). * * @return this */ insertStringNT(value, offset, encoding) { utils_1.checkOffsetValue(offset); // Write Values this.insertString(value, offset, encoding); this.insertUInt8(0x00, offset + value.length); return this; } /** * Writes a null-terminated String. * * @param value { String } The String value to write. * @param arg2 { Number | String } The offset to write the string to, or the BufferEncoding to use. * @param encoding { String } The BufferEncoding to use for writing strings (defaults to instance encoding). * * @return this */ writeStringNT(value, arg2, encoding) { // Write Values this.writeString(value, arg2, encoding); this.writeUInt8(0x00, typeof arg2 === 'number' ? arg2 + value.length : this.writeOffset); return this; } // Buffers /** * Reads a Buffer from the internal read position. * * @param length { Number } The length of data to read as a Buffer. * * @return { Buffer } */ readBuffer(length) { if (typeof length !== 'undefined') { utils_1.checkLengthValue(length); } const lengthVal = typeof length === 'number' ? length : this.length; const endPoint = Math.min(this.length, this._readOffset + lengthVal); // Read buffer value const value = this._buff.slice(this._readOffset, endPoint); // Increment internal Buffer read offset this._readOffset = endPoint; return value; } /** * Writes a Buffer to the current write position. * * @param value { Buffer } The Buffer to write. * @param offset { Number } The offset to write the Buffer to. * * @return this */ insertBuffer(value, offset) { utils_1.checkOffsetValue(offset); return this._handleBuffer(value, true, offset); } /** * Writes a Buffer to the current write position. * * @param value { Buffer } The Buffer to write. * @param offset { Number } The offset to write the Buffer to. * * @return this */ writeBuffer(value, offset) { return this._handleBuffer(value, false, offset); } /** * Reads a null-terminated Buffer from the current read poisiton. * * @return { Buffer } */ readBufferNT() { // Set null character position to the end SmartBuffer instance. let nullPos = this.length; // Find next null character (if one is not found, default from above is used) for (let i = this._readOffset; i < this.length; i++) { if (this._buff[i] === 0x00) { nullPos = i; break; } } // Read value const value = this._buff.slice(this._readOffset, nullPos); // Increment internal Buffer read offset this._readOffset = nullPos + 1; return value; } /** * Inserts a null-terminated Buffer. * * @param value { Buffer } The Buffer to write. * @param offset { Number } The offset to write the Buffer to. * * @return this */ insertBufferNT(value, offset) { utils_1.checkOffsetValue(offset); // Write Values this.insertBuffer(value, offset); this.insertUInt8(0x00, offset + value.length); return this; } /** * Writes a null-terminated Buffer. * * @param value { Buffer } The Buffer to write. * @param offset { Number } The offset to write the Buffer to. * * @return this */ writeBufferNT(value, offset) { // Checks for valid numberic value; if (typeof offset !== 'undefined') { utils_1.checkOffsetValue(offset); } // Write Values this.writeBuffer(value, offset); this.writeUInt8(0x00, typeof offset === 'number' ? offset + value.length : this._writeOffset); return this; } /** * Clears the SmartBuffer instance to its original empty state. */ clear() { this._writeOffset = 0; this._readOffset = 0; this.length = 0; return this; } /** * Gets the remaining data left to be read from the SmartBuffer instance. * * @return { Number } */ remaining() { return this.length - this._readOffset; } /** * Gets the current read offset value of the SmartBuffer instance. * * @return { Number } */ get readOffset() { return this._readOffset; } /** * Sets the read offset value of the SmartBuffer instance. * * @param offset { Number } - The offset value to set. */ set readOffset(offset) { utils_1.checkOffsetValue(offset); // Check for bounds. utils_1.checkTargetOffset(offset, this); this._readOffset = offset; } /** * Gets the current write offset value of the SmartBuffer instance. * * @return { Number } */ get writeOffset() { return this._writeOffset; } /** * Sets the write offset value of the SmartBuffer instance. * * @param offset { Number } - The offset value to set. */ set writeOffset(offset) { utils_1.checkOffsetValue(offset); // Check for bounds. utils_1.checkTargetOffset(offset, this); this._writeOffset = offset; } /** * Gets the currently set string encoding of the SmartBuffer instance. * * @return { BufferEncoding } The string Buffer encoding currently set. */ get encoding() { return this._encoding; } /** * Sets the string encoding of the SmartBuffer instance. * * @param encoding { BufferEncoding } The string Buffer encoding to set. */ set encoding(encoding) { utils_1.checkEncoding(encoding); this._encoding = encoding; } /** * Gets the underlying internal Buffer. (This includes unmanaged data in the Buffer) * * @return { Buffer } The Buffer value. */ get internalBuffer() { return this._buff; } /** * Gets the value of the internal managed Buffer (Includes managed data only) * * @param { Buffer } */ toBuffer() { return this._buff.slice(0, this.length); } /** * Gets the String value of the internal managed Buffer * * @param encoding { String } The BufferEncoding to display the Buffer as (defaults to instance level encoding). */ toString(encoding) { const encodingVal = typeof encoding === 'string' ? encoding : this._encoding; // Check for invalid encoding. utils_1.checkEncoding(encodingVal); return this._buff.toString(encodingVal, 0, this.length); } /** * Destroys the SmartBuffer instance. */ destroy() { this.clear(); return this; } /** * Handles inserting and writing strings. * * @param value { String } The String value to insert. * @param isInsert { Boolean } True if inserting a string, false if writing. * @param arg2 { Number | String } The offset to insert the string at, or the BufferEncoding to use. * @param encoding { String } The BufferEncoding to use for writing strings (defaults to instance encoding). */ _handleString(value, isInsert, arg3, encoding) { let offsetVal = this._writeOffset; let encodingVal = this._encoding; // Check for offset if (typeof arg3 === 'number') { offsetVal = arg3; // Check for encoding } else if (typeof arg3 === 'string') { utils_1.checkEncoding(arg3); encodingVal = arg3; } // Check for encoding (third param) if (typeof encoding === 'string') { utils_1.checkEncoding(encoding); encodingVal = encoding; } // Calculate bytelength of string. const byteLength = Buffer.byteLength(value, encodingVal); // Ensure there is enough internal Buffer capacity. if (isInsert) { this.ensureInsertable(byteLength, offsetVal); } else { this._ensureWriteable(byteLength, offsetVal); } // Write value this._buff.write(value, offsetVal, byteLength, encodingVal); // Increment internal Buffer write offset; if (isInsert) { this._writeOffset += byteLength; } else { // If an offset was given, check to see if we wrote beyond the current writeOffset. if (typeof arg3 === 'number') { this._writeOffset = Math.max(this._writeOffset, offsetVal + byteLength); } else { // If no offset was given, we wrote to the end of the SmartBuffer so increment writeOffset. this._writeOffset += byteLength; } } return this; } /** * Handles writing or insert of a Buffer. * * @param value { Buffer } The Buffer to write. * @param offset { Number } The offset to write the Buffer to. */ _handleBuffer(value, isInsert, offset) { const offsetVal = typeof offset === 'number' ? offset : this._writeOffset; // Ensure there is enough internal Buffer capacity. if (isInsert) { this.ensureInsertable(value.length, offsetVal); } else { this._ensureWriteable(value.length, offsetVal); } // Write buffer value value.copy(this._buff, offsetVal); // Increment internal Buffer write offset; if (isInsert) { this._writeOffset += value.length; } else { // If an offset was given, check to see if we wrote beyond the current writeOffset. if (typeof offset === 'number') { this._writeOffset = Math.max(this._writeOffset, offsetVal + value.length); } else { // If no offset was given, we wrote to the end of the SmartBuffer so increment writeOffset. this._writeOffset += value.length; } } return this; } /** * Ensures that the internal Buffer is large enough to read data. * * @param length { Number } The length of the data that needs to be read. * @param offset { Number } The offset of the data that needs to be read. */ ensureReadable(length, offset) { // Offset value defaults to managed read offset. let offsetVal = this._readOffset; // If an offset was provided, use it. if (typeof offset !== 'undefined') { // Checks for valid numberic value; utils_1.checkOffsetValue(offset); // Overide with custom offset. offsetVal = offset; } // Checks if offset is below zero, or the offset+length offset is beyond the total length of the managed data. if (offsetVal < 0 || offsetVal + length > this.length) { throw new Error(utils_1.ERRORS.INVALID_READ_BEYOND_BOUNDS); } } /** * Ensures that the internal Buffer is large enough to insert data. * * @param dataLength { Number } The length of the data that needs to be written. * @param offset { Number } The offset of the data to be written. */ ensureInsertable(dataLength, offset) { // Checks for valid numberic value; utils_1.checkOffsetValue(offset); // Ensure there is enough internal Buffer capacity. this._ensureCapacity(this.length + dataLength); // If an offset was provided and its not the very end of the buffer, copy data into appropriate location in regards to the offset. if (offset < this.length) { this._buff.copy(this._buff, offset + dataLength, offset, this._buff.length); } // Adjust tracked smart buffer length if (offset + dataLength > this.length) { this.length = offset + dataLength; } else { this.length += dataLength; } } /** * Ensures that the internal Buffer is large enough to write data. * * @param dataLength { Number } The length of the data that needs to be written. * @param offset { Number } The offset of the data to be written (defaults to writeOffset). */ _ensureWriteable(dataLength, offset) { const offsetVal = typeof offset === 'number' ? offset : this._writeOffset; // Ensure enough capacity to write data. this._ensureCapacity(offsetVal + dataLength); // Adjust SmartBuffer length (if offset + length is larger than managed length, adjust length) if (offsetVal + dataLength > this.length) { this.length = offsetVal + dataLength; } } /** * Ensures that the internal Buffer is large enough to write at least the given amount of data. * * @param minLength { Number } The minimum length of the data needs to be written. */ _ensureCapacity(minLength) { const oldLength = this._buff.length; if (minLength > oldLength) { let data = this._buff; let newLength = (oldLength * 3) / 2 + 1; if (newLength < minLength) { newLength = minLength; } this._buff = Buffer.allocUnsafe(newLength); data.copy(this._buff, 0, 0, oldLength); } } /** * Reads a numeric number value using the provided function. * * @typeparam T { number | bigint } The type of the value to be read * * @param func { Function(offset: number) => number } The function to read data on the internal Buffer with. * @param byteSize { Number } The number of bytes read. * @param offset { Number } The offset to read from (optional). When this is not provided, the managed readOffset is used instead. * * @returns { T } the number value */ _readNumberValue(func, byteSize, offset) { this.ensureReadable(byteSize, offset); // Call Buffer.readXXXX(); const value = func.call(this._buff, typeof offset === 'number' ? offset : this._readOffset); // Adjust internal read offset if an optional read offset was not provided. if (typeof offset === 'undefined') { this._readOffset += byteSize; } return value; } /** * Inserts a numeric number value based on the given offset and value. * * @typeparam T { number | bigint } The type of the value to be written * * @param func { Function(offset: T, offset?) => number} The function to write data on the internal Buffer with. * @param byteSize { Number } The number of bytes written. * @param value { T } The number value to write. * @param offset { Number } the offset to write the number at (REQUIRED). * * @returns SmartBuffer this buffer */ _insertNumberValue(func, byteSize, value, offset) { // Check for invalid offset values. utils_1.checkOffsetValue(offset); // Ensure there is enough internal Buffer capacity. (raw offset is passed) this.ensureInsertable(byteSize, offset); // Call buffer.writeXXXX(); func.call(this._buff, value, offset); // Adjusts internally managed write offset. this._writeOffset += byteSize; return this; } /** * Writes a numeric number value based on the given offset and value. * * @typeparam T { number | bigint } The type of the value to be written * * @param func { Function(offset: T, offset?) => number} The function to write data on the internal Buffer with. * @param byteSize { Number } The number of bytes written. * @param value { T } The number value to write. * @param offset { Number } the offset to write the number at (REQUIRED). * * @returns SmartBuffer this buffer */ _writeNumberValue(func, byteSize, value, offset) { // If an offset was provided, validate it. if (typeof offset === 'number') { // Check if we're writing beyond the bounds of the managed data. if (offset < 0) { throw new Error(utils_1.ERRORS.INVALID_WRITE_BEYOND_BOUNDS); } utils_1.checkOffsetValue(offset); } // Default to writeOffset if no offset value was given. const offsetVal = typeof offset === 'number' ? offset : this._writeOffset; // Ensure there is enough internal Buffer capacity. (raw offset is passed) this._ensureWriteable(byteSize, offsetVal); func.call(this._buff, value, offsetVal); // If an offset was given, check to see if we wrote beyond the current writeOffset. if (typeof offset === 'number') { this._writeOffset = Math.max(this._writeOffset, offsetVal + byteSize); } else { // If no numeric offset was given, we wrote to the end of the SmartBuffer so increment writeOffset. this._writeOffset += byteSize; } return this; } } exports.SmartBuffer = SmartBuffer; //# sourceMappingURL=smartbuffer.js.map