UNPKG

asbytearray

Version:

Simple implementation of the ByteArray from ActionScript3 in Node.js

430 lines (429 loc) 13.5 kB
// src/asbytearray.ts import * as zlib from "zlib"; var ByteArray = class { buffer; _position = 0; _endian = "bigEndian" /* BIG_ENDIAN */; constructor(buffer = Buffer.allocUnsafe(0)) { this.buffer = buffer; } /** * Moves, or returns the current position, in bytes, of the file * pointer into the ByteArray object. This is the point at which the * next call to a read method starts reading or a write method starts * writing. */ get position() { return this._position; } /** * Moves, or returns the current position, in bytes, of the file * pointer into the ByteArray object. This is the point at which the * next call to a read method starts reading or a write method starts * writing. */ set position(value) { this._position = value; } /** * Changes or reads the byte order for the data; either * Endian.BIG_ENDIAN or Endian.LITTLE_ENDIAN. */ get endian() { return this._endian; } /** * Changes or reads the byte order for the data; either * Endian.BIG_ENDIAN or Endian.LITTLE_ENDIAN. */ set endian(value) { this._endian = value; } /** * The length of the ByteArray object, in bytes. * * If the length is set to a value that is larger than the current * length, the right side of the byte array is filled with zeros. * * If the length is set to a value that is smaller than the current * length, the byte array is truncated. */ get length() { return this.buffer.byteLength; } /** * The length of the ByteArray object, in bytes. * * If the length is set to a value that is larger than the current * length, the right side of the byte array is filled with zeros. * * If the length is set to a value that is smaller than the current * length, the byte array is truncated. */ set length(value) { if (value > this.buffer.length) { const newData = Buffer.alloc(value); this.buffer.copy(newData); this.buffer = newData; } else if (value < this.buffer.length) { const newData = Buffer.allocUnsafe(value); this.buffer.copy(newData, 0, 0, value); this.buffer = newData; } } /** * The number of bytes of data available for reading from the current * position in the byte array to the end of the array. * * Use the bytesAvailable property in conjunction with the read methods * each time you access a ByteArray object to ensure that you are * reading valid data. */ get bytesAvailable() { return this.buffer.byteLength - this.position; } /** * Clears the contents of the byte array and resets the length and * position properties to 0. Calling this method explicitly frees up * the memory used by the ByteArray instance. */ clear() { this.buffer = Buffer.allocUnsafe(0); this.position = 0; } /** * zlib deflate */ compress() { const compressedData = zlib.deflateSync(this.buffer); this.buffer = compressedData; this.position = 0; } /** * zlib inflate */ uncompress() { const uncompressedData = zlib.inflateSync(this.buffer); this.buffer = uncompressedData; this.position = 0; } /** * Writes a sequence of length bytes from the specified byte array, * bytes, starting offset(zero-based index) bytes into the byte stream. * * If the length parameter is omitted, the default length of 0 is used; * the method writes the entire buffer starting at offset. If the * offset parameter is also omitted, the entire buffer is written. * * * * If offset or length is out of range, they are clamped to the * beginning and end of the bytes array. * * @param bytes The ByteArray object. * * @param offset A zero-based index indicating the position into the * array to begin writing. * * @param length An unsigned integer indicating how far into the buffer * to write. */ writeBytes(bytes, offset = 0, length) { length = length || bytes.length - offset; this.checkBuffer(length); bytes.buffer.copy(this.buffer, this.position, offset, offset + length); this.position += length; } /** * Reads the number of data bytes, specified by the length parameter, * from the byte stream. The bytes are read into the ByteArray object * specified by the bytes parameter, and the bytes are written into the * destination ByteArray starting at the position specified by offset. * * @param bytes The ByteArray object to read data into. * * @param offset The offset (position) in bytes at which the read data * should be written. * * @param length The number of bytes to read. The default value of 0 * causes all available data to be read. */ readBytes(bytes, offset = 0, length) { length = length || this.bytesAvailable; if (bytes.length - bytes.position < length) { bytes.buffer = Buffer.concat([bytes.buffer, Buffer.allocUnsafe(length)]); } this.buffer.copy(bytes.buffer, offset, this.position, this.position + length); this.position += length; } /** * Writes a Boolean value. A single byte is written according to the * value parameter, either 1 if true or 0 if false. * * @param value A Boolean value determining which byte is written. If * the parameter is true, the method writes a 1; if false, the * method writes a 0. */ writeBoolean(value) { this.checkBuffer(1); this.buffer.writeInt8(Number(value), this.position); this.position += 1; } /** * Reads a Boolean value from the byte stream. A single byte is read, * and true is returned if the byte is nonzero, false otherwise. * * @return Returns true if the byte is nonzero, false otherwise. */ readBoolean() { const result = this.buffer.readInt8(this.position) > 0; this.position += 1; return result; } /** * Writes a byte to the byte stream. * * The low 8 bits of the parameter are used. The high 24 bits are * ignored. * * @param value A integer. The low 8 bits are written to the byte * stream. */ writeByte(value) { this.checkBuffer(1); this.buffer.writeUInt8(value & 255, this.position); this.position += 1; } /** * Reads a signed byte from the byte stream. * * The returned value is in the range -128 to 127. * * @return An integer between -128 and 127. */ readByte() { const result = this.buffer.readInt8(this.position); this.position += 1; return result; } /** * Reads an unsigned byte from the byte stream. * * The returned value is in the range 0 to 255. * * @return A 32-bit unsigned integer between 0 and 255. */ readUnsignedByte() { const result = this.buffer.readUInt8(this.position); this.position += 1; return result; } /** * Writes a 16-bit integer to the byte stream. The low 16 bits of the * parameter are used. The high 16 bits are ignored. * * @param value integer, whose low 16 bits are written to the * byte stream. */ writeShort(value) { this.checkBuffer(2); if (this.endian === "bigEndian" /* BIG_ENDIAN */) { this.buffer.writeUInt16BE(value & 65535, this.position); } else { this.buffer.writeUInt16LE(value & 65535, this.position); } this.position += 2; } /** * Reads a signed 16-bit integer from the byte stream. * * The returned value is in the range -32768 to 32767. * * @return A 16-bit signed integer between -32768 and 32767. */ readShort() { const result = this.endian === "bigEndian" /* BIG_ENDIAN */ ? this.buffer.readInt16BE(this.position) : this.buffer.readInt16LE(this.position); this.position += 2; return result; } /** * Reads an unsigned 16-bit integer from the byte stream. * * The returned value is in the range 0 to 65535. * * @return A 16-bit unsigned integer between 0 and 65535. */ readUnsignedShort() { const result = this.endian === "bigEndian" /* BIG_ENDIAN */ ? this.buffer.readUInt16BE(this.position) : this.buffer.readUInt16LE(this.position); this.position += 2; return result; } /** * Writes a 32-bit integer to the byte stream. * * @param value An integer to write to the byte stream. */ writeInt(value) { this.checkBuffer(4); if (this.endian === "bigEndian" /* BIG_ENDIAN */) { this.buffer.writeInt32BE(value & 4294967295, this.position); } else { this.buffer.writeInt32LE(value & 4294967295, this.position); } this.position += 4; } /** * Reads a signed 32-bit integer from the byte stream. * * The returned value is in the range -2147483648 to 2147483647. * * @return A 32-bit signed integer between -2147483648 and 2147483647. */ readInt() { const result = this.endian === "bigEndian" /* BIG_ENDIAN */ ? this.buffer.readInt32BE(this.position) : this.buffer.readInt32LE(this.position); this.position += 4; return result; } /** * Reads an unsigned 32-bit integer from the byte stream. * * The returned value is in the range 0 to 4294967295. * * @return A 32-bit unsigned integer between 0 and 4294967295. */ readUnsignedInt() { const result = this.endian === "bigEndian" /* BIG_ENDIAN */ ? this.buffer.readUInt32BE(this.position) : this.buffer.readUInt32LE(this.position); this.position += 4; return result; } /** * Writes an IEEE 754 single-precision (32-bit) floating-point number * to the byte stream. * * @param value A single-precision (32-bit) floating-point number. */ writeFloat(value) { this.checkBuffer(4); if (this.endian === "bigEndian" /* BIG_ENDIAN */) { this.buffer.writeFloatBE(value, this.position); } else { this.buffer.writeFloatLE(value, this.position); } this.position += 4; } /** * Reads a signed 32-bit integer from the byte stream. * * The returned value is in the range -2147483648 to 2147483647. * * @return A 32-bit signed integer between -2147483648 and 2147483647. */ readFloat() { const result = this.endian === "bigEndian" /* BIG_ENDIAN */ ? this.buffer.readFloatBE(this.position) : this.buffer.readFloatLE(this.position); this.position += 4; return result; } /** * Writes an IEEE 754 double-precision (64-bit) floating-point number * to the byte stream. * * @param value A double-precision (64-bit) floating-point number. */ writeDouble(value) { this.checkBuffer(8); if (this.endian === "bigEndian" /* BIG_ENDIAN */) { this.buffer.writeDoubleBE(value, this.position); } else { this.buffer.writeDoubleLE(value, this.position); } this.position += 8; } /** * Reads an IEEE 754 single-precision (32-bit) floating-point number * from the byte stream. * * @return A single-precision (32-bit) floating-point number. * * @throws EOFError There is not sufficient data available to * read. */ readDouble() { const result = this.endian === "bigEndian" /* BIG_ENDIAN */ ? this.buffer.readDoubleBE(this.position) : this.buffer.readDoubleLE(this.position); this.position += 8; return result; } /** * Writes a UTF-8 string to the byte stream. The length of the UTF-8 * string in bytes is written first, as a 16-bit integer, followed by * the bytes representing the characters of the string. * * @param value The string value to be written. * * @throws RangeError If the length is larger than 65535. */ writeUTF(value) { const length = Buffer.byteLength(value, "utf8"); if (length > 65535) { throw new RangeError(); } this.writeShort(length); this.checkBuffer(length); this.buffer.write(value, this.position, "utf8"); this.position += length; } /** * Reads a UTF-8 string from the byte stream. The string is assumed to * be prefixed with an unsigned short indicating the length in bytes. * * @return UTF-8 encoded string. */ readUTF() { const length = this.readShort(); const value = this.buffer.toString("utf8", this.position, this.position + length); this.position += length; return value; } /** * Writes a UTF-8 string to the byte stream. Similar to the writeUTF() * method, but writeUTFBytes() does not prefix the string with a 16-bit * length word. * * @param value The string value to be written. */ writeUTFBytes(value) { const byteLength = Buffer.byteLength(value); this.checkBuffer(byteLength); this.buffer.write(value, this.position, "utf8"); this.position += byteLength; } /** * Reads a sequence of UTF-8 bytes specified by the length parameter * from the byte stream and returns a string. * * @param length An unsigned short indicating the length of the UTF-8 * bytes. * * @return A string composed of the UTF-8 bytes of the specified * length. */ readUTFBytes(length) { const result = this.buffer.toString("utf8", this.position, this.position + length); this.position += length; return result; } checkBuffer(size) { const diff = this.buffer.length - this.position; if (diff < size) { this.buffer = Buffer.concat([this.buffer, Buffer.allocUnsafe(size)]); } } }; var Endian = /* @__PURE__ */ ((Endian2) => { Endian2["BIG_ENDIAN"] = "bigEndian"; Endian2["LITTLE_ENDIAN"] = "littleEndian"; return Endian2; })(Endian || {}); export { ByteArray, Endian };