2025-06-21 00:41:45 +03:00

175 lines
3.9 KiB
JavaScript

class ByteStream {
constructor(buffer = null) {
this.buffer = buffer || Buffer.alloc(0)
this.offset = 0
}
readUInt8() {
if (this.offset >= this.buffer.length) {
throw new Error("ByteStream: Cannot read beyond buffer length")
}
const value = this.buffer.readUInt8(this.offset)
this.offset += 1
return value
}
readUInt16() {
if (this.offset + 2 > this.buffer.length) {
throw new Error("ByteStream: Cannot read beyond buffer length")
}
const value = this.buffer.readUInt16BE(this.offset)
this.offset += 2
return value
}
readUInt24() {
if (this.offset + 3 > this.buffer.length) {
throw new Error("ByteStream: Cannot read beyond buffer length")
}
const value =
(this.buffer.readUInt8(this.offset) << 16) |
(this.buffer.readUInt8(this.offset + 1) << 8) |
this.buffer.readUInt8(this.offset + 2)
this.offset += 3
return value
}
readUInt32() {
if (this.offset + 4 > this.buffer.length) {
throw new Error("ByteStream: Cannot read beyond buffer length")
}
const value = this.buffer.readUInt32BE(this.offset)
this.offset += 4
return value
}
readInt32() {
if (this.offset + 4 > this.buffer.length) {
throw new Error("ByteStream: Cannot read beyond buffer length")
}
const value = this.buffer.readInt32BE(this.offset)
this.offset += 4
return value
}
readString() {
const length = this.readUInt32()
if (length === 0) return ""
if (this.offset + length > this.buffer.length) {
throw new Error("ByteStream: Cannot read beyond buffer length")
}
const value = this.buffer.toString("utf8", this.offset, this.offset + length)
this.offset += length
return value
}
readBytes(length) {
if (this.offset + length > this.buffer.length) {
throw new Error("ByteStream: Cannot read beyond buffer length")
}
const value = this.buffer.slice(this.offset, this.offset + length)
this.offset += length
return value
}
writeUInt8(value) {
const buf = Buffer.alloc(1)
buf.writeUInt8(value, 0)
this.buffer = Buffer.concat([this.buffer, buf])
return this
}
writeUInt16(value) {
const buf = Buffer.alloc(2)
buf.writeUInt16BE(value, 0)
this.buffer = Buffer.concat([this.buffer, buf])
return this
}
writeUInt24(value) {
const buf = Buffer.alloc(3)
buf.writeUInt8((value >> 16) & 0xff, 0)
buf.writeUInt8((value >> 8) & 0xff, 1)
buf.writeUInt8(value & 0xff, 2)
this.buffer = Buffer.concat([this.buffer, buf])
return this
}
writeUInt32(value) {
const buf = Buffer.alloc(4)
buf.writeUInt32BE(value, 0)
this.buffer = Buffer.concat([this.buffer, buf])
return this
}
writeInt32(value) {
const buf = Buffer.alloc(4)
buf.writeInt32BE(value, 0)
this.buffer = Buffer.concat([this.buffer, buf])
return this
}
writeString(value) {
this.writeUInt32(value.length)
if (value.length > 0) {
const buf = Buffer.from(value, "utf8")
this.buffer = Buffer.concat([this.buffer, buf])
}
return this
}
writeBytes(bytes) {
this.buffer = Buffer.concat([this.buffer, bytes])
return this
}
// Utility methods
getBuffer() {
return this.buffer
}
getLength() {
return this.buffer.length
}
getRemainingLength() {
return this.buffer.length - this.offset
}
getOffset() {
return this.offset
}
setOffset(offset) {
if (offset < 0 || offset > this.buffer.length) {
throw new Error("ByteStream: Invalid offset")
}
this.offset = offset
return this
}
reset() {
this.buffer = Buffer.alloc(0)
this.offset = 0
return this
}
clone() {
const cloned = new ByteStream(Buffer.from(this.buffer))
cloned.offset = this.offset
return cloned
}
toHex() {
return this.buffer.toString("hex")
}
static fromHex(hexString) {
return new ByteStream(Buffer.from(hexString, "hex"))
}
}
module.exports = ByteStream