@runejs/core
Version:
Core logging, networking, and buffer functionality for RuneJS applications.
269 lines • 9.04 kB
JavaScript
"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