UNPKG

@runejs/core

Version:

Core logging, networking, and buffer functionality for RuneJS applications.

269 lines 9.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ByteBuffer = exports.ENDIAN_SUFFIX = exports.BIT_LENGTH = exports.BYTE_LENGTH = exports.MAX_SIGNED_LENGTHS = void 0; const buffer_1 = require("buffer"); const logger_1 = require("../logger"); exports.MAX_SIGNED_LENGTHS = { 'byte': 127, 'short': 32767, 'smart': -1, 'int24': 8388607, 'int': 2147483647, 'long': BigInt('9223372036854775807') }; exports.BYTE_LENGTH = { 'byte': 1, 'short': 2, 'smart': -1, 'int24': 3, 'int': 4, 'long': 8 }; exports.BIT_LENGTH = { 'byte': 8, 'short': 16, 'smart': -1, 'int24': 24, 'int': 32, 'long': 64 }; exports.ENDIAN_SUFFIX = { 'little_endian': 'LE', 'big_endian': 'BE', 'middle_endian_1': 'ME1', 'middle_endian_2': 'ME2' }; const BIT_MASKS = []; for (let i = 0; i < 32; i++) { BIT_MASKS.push((1 << i) - 1); } class ByteBuffer extends Uint8Array { constructor() { super(...arguments); this._writerIndex = 0; this._readerIndex = 0; } static getType(type = 'byte') { return type.toLowerCase(); } static getSignage(signed) { return (signed.length === 1 ? signed : signed.charAt(0)).toUpperCase(); } static getEndianness(endian) { return (endian.length < 4 ? endian : exports.ENDIAN_SUFFIX[endian.toLowerCase()]).toUpperCase(); } static fromNodeBuffer(buffer) { return new ByteBuffer(buffer); } static toNodeBuffer(byteBuffer) { return byteBuffer.toNodeBuffer(); } toNodeBuffer() { return buffer_1.Buffer.from(this); } get(type = 'byte', signed = 'signed', endian = 'be') { type = ByteBuffer.getType(type); signed = ByteBuffer.getSignage(signed); endian = ByteBuffer.getEndianness(endian); const readerIndex = this._readerIndex; if (type === 'smart') { return this.getSmart(readerIndex, signed); } else if (type === 'string') { return this.getString(); } else { const size = exports.BYTE_LENGTH[type]; const signedChar = signed === 'S' ? '' : 'U'; const bitLength = exports.BIT_LENGTH[type]; const suffix = type === 'byte' ? '' : endian; const smol = type === 'long' ? 'Big' : ''; this._readerIndex += size; const methodName = `read${signedChar}${smol}Int${bitLength}${suffix}`; try { return this[methodName](readerIndex); } catch (error) { logger_1.logger.error(`Error reading ${methodName}:`, error); return null; } } } put(value, type = 'byte', endian = 'be') { const writerIndex = this._writerIndex; type = ByteBuffer.getType(type); endian = ByteBuffer.getEndianness(endian); if (type === 'smart') { return this.putSmart(value); } else if (type === 'string') { if (typeof value === 'string') { return this.putString(value); } } else { const maxSignedLength = exports.MAX_SIGNED_LENGTHS[type]; const size = exports.BYTE_LENGTH[type]; const signedChar = value > maxSignedLength ? 'U' : ''; const lenChars = exports.BIT_LENGTH[type]; const suffix = type === 'byte' ? '' : endian; const smol = type === 'long' ? 'Big' : ''; this._writerIndex += size; const methodName = `write${signedChar}${smol}Int${lenChars}${suffix}`; try { return this[methodName](value, writerIndex); } catch (error) { logger_1.logger.error(`Error writing ${methodName}:`, error); return null; } } return null; } at(index, signed = 'signed') { return ByteBuffer.getSignage(signed) === 'S' ? this.readInt8(index) : this.readUInt8(index); } getSlice(position, length) { return new ByteBuffer(this.slice(position, position + length)); } putBytes(from, fromStart, fromEnd) { from.copy(this, this.writerIndex, fromStart || 0, fromEnd || from.length); this.writerIndex = (this.writerIndex + from.length); return this; } getBytes(to, length) { this.copy(to, 0, this.readerIndex, this.readerIndex + length); this.readerIndex += length; } putBits(bitCount, value) { let byteIndex = this.bitIndex >> 3; let bitOffset = 8 - (this.bitIndex & 7); this.bitIndex += bitCount; for (; bitCount > bitOffset; bitOffset = 8) { this[byteIndex] &= ~BIT_MASKS[bitOffset]; this[byteIndex++] |= (value >> (bitCount - bitOffset)) & BIT_MASKS[bitOffset]; bitCount -= bitOffset; } if (bitCount == bitOffset) { this[byteIndex] &= ~BIT_MASKS[bitOffset]; this[byteIndex] |= value & BIT_MASKS[bitOffset]; } else { this[byteIndex] &= ~(BIT_MASKS[bitCount] << (bitOffset - bitCount)); this[byteIndex] |= (value & BIT_MASKS[bitCount]) << (bitOffset - bitCount); } return this; } openBitBuffer() { this.bitIndex = this.writerIndex * 8; return this; } closeBitBuffer() { this.writerIndex = Math.floor((this.bitIndex + 7) / 8); } flipWriter() { const newBuffer = new ByteBuffer(this.writerIndex); this.copy(newBuffer, 0, 0, this.writerIndex); return newBuffer; } flipReader() { const newBuffer = new ByteBuffer(this.readerIndex); this.copy(newBuffer, 0, 0, this.readerIndex); return newBuffer; } getString(terminatingChar = 0) { const bytes = []; let b; while ((b = this.get('byte')) !== terminatingChar) { bytes.push(b); } return buffer_1.Buffer.from(bytes).toString(); } putString(value) { const encoder = new TextEncoder(); const bytes = encoder.encode(value); for (const byte of bytes) { this.put(byte); } this.put(0); // end of line return this; } putSmart(value) { if (value >= 128) { this.put(value, 'short'); } else { this.put(value, 'byte'); } return this; } getSmart(offset, signed = 'SIGNED') { const peek = this[offset]; const signedString = ByteBuffer.getSignage(signed); if (peek < 128) { return this.get('byte', 'u') - (signedString === 'S' ? 0 : 64); } else { return this.get('short', 'u') - (signedString === 'S' ? 32768 : 49152); } } readUInt24BE(offset) { return ((this[offset] & 0xff) << 16) + ((this[offset + 1] & 0xff) << 8) + (this[offset + 2] & 0xff); } readInt24BE(offset) { return ((this[offset]) << 16) + ((this[offset + 1]) << 8) + (this[offset + 2]); } readUInt24LE(offset) { return ((this[offset + 2] & 0xff) << 16) + ((this[offset + 1] & 0xff) << 8) + (this[offset] & 0xff); } readInt24LE(offset) { return ((this[offset + 2]) << 16) + ((this[offset + 1]) << 8) + (this[offset]); } writeUInt24BE(value, offset) { this[offset] = ((value & 0xff) >> 16); this[offset + 1] = ((value & 0xff) >> 8); this[offset + 2] = (value & 0xff); } writeInt24BE(value, offset) { this[offset] = (value >> 16); this[offset + 1] = (value >> 8); this[offset + 2] = (value); } writeUInt24LE(value, offset) { this[offset + 2] = ((value & 0xff) >> 16); this[offset + 1] = ((value & 0xff) >> 8); this[offset] = (value & 0xff); } writeInt24LE(value, offset) { this[offset + 2] = (value >> 16); this[offset + 1] = (value >> 8); this[offset] = (value); } get writerIndex() { return this._writerIndex; } set writerIndex(value) { this._writerIndex = value; } get readerIndex() { return this._readerIndex; } set readerIndex(value) { this._readerIndex = value; } get readable() { return this.length - this._readerIndex; } get writable() { return this.length - this._writerIndex; } get bitIndex() { return this._bitIndex; } set bitIndex(value) { this._bitIndex = value; } } exports.ByteBuffer = ByteBuffer; Object.setPrototypeOf(ByteBuffer.prototype, buffer_1.Buffer.prototype); //# sourceMappingURL=byte-buffer.js.map