@lavacoffee/datarw
Version:
A binary data reader/writer aim to work with lavaplayer MessageIO
141 lines (140 loc) • 4.66 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataWriter = void 0;
const InitialSize = 2048;
/** Binary data writer */
class DataWriter {
constructor() {
/** The binary data */
this.bytes = new Uint8Array(InitialSize);
/** The data view of the binary data */
this.view = new DataView(this.bytes.buffer, this.bytes.byteOffset, this.bytes.byteLength);
/** The binary data size */
this.size = 0;
}
/** Finish and get the binary data */
finish(flags) {
let info = this.size;
if (typeof flags === "number" && !isNaN(flags)) {
info |= flags << 30;
}
const bytes = new Uint8Array(4 + this.size);
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
view.setInt32(0, info);
bytes.set(this.bytes.slice(0, this.size), 4);
this.size = 0;
return bytes;
}
/** Write 8 bit integer */
write(int) {
this.view.setInt8(this._advance(), int);
}
/** Write 8 bit unsigned integer */
writeU(uint) {
this.view.setUint8(this._advance(), uint);
}
/** Write 8 bit boolean */
writeBool(bool) {
this.write(bool ? 1 : 0);
}
/** Write 16 bit integer */
writeShort(int) {
this.view.setInt16(this._advance(2), int);
}
/** Write 16 bit unsigned integer */
writeUShort(uint) {
this.view.setUint16(this._advance(2), uint);
}
/** Write 32 bit integer */
writeInt(int) {
this.view.setInt32(this._advance(4), int);
}
/** Write 32 bit unsigned integer */
writeUInt(uint) {
this.view.setUint32(this._advance(4), uint);
}
/** Write 32 bit float */
writeFloat(float) {
this.view.setFloat32(this._advance(4), float);
}
/** Write 64 bit bigint long */
writeBigLong(long) {
this.view.setBigInt64(this._advance(8), long);
}
/** Write 64 bit bigint unsigned long */
writeBigULong(ulong) {
this.view.setBigUint64(this._advance(8), ulong);
}
/** Write 64 bit long */
writeLong(long) {
this.writeBigLong(BigInt(long));
}
/** Write 64 bit unsigned long */
writeULong(ulong) {
this.writeBigULong(BigInt(ulong));
}
/** Write 64 bit double */
writeDouble(double) {
this.view.setFloat64(this._advance(8), double);
}
/** Write modified utf-8 string */
writeUTF(str) {
const strLength = str.length;
let utfLength = strLength;
for (let i = 0; i < strLength; i++) {
const char = str.charCodeAt(i);
if (char >= 0x80 || char === 0) {
utfLength = (char >= 0x800) ? 2 : 1;
}
}
if (utfLength > 65535)
throw new Error("String is too long (max 65535)");
this.writeUShort(utfLength);
this._ensure(utfLength);
let index = 0;
for (; index < strLength; index++) {
const char = str.charCodeAt(index);
if (char >= 0x80 || char === 0)
break;
this.writeU(char);
}
for (; index < strLength; index++) {
const char = str.charCodeAt(index);
if (char < 0x80 && char !== 0) {
this.writeU(char);
}
else if (char >= 0x800) {
this.writeU(0xe0 | ((char >> 12) & 0x0f));
this.writeU(0x80 | ((char >> 6) & 0x3f));
this.writeU(0x80 | ((char >> 0) & 0x3f));
}
else {
this.writeU(0xc0 | ((char >> 6) & 0x1f));
this.writeU(0x80 | ((char >> 0) & 0x3f));
}
}
}
/** Write modified utf-8 string, only if the provided value is a string */
writeNullableText(str) {
this.writeBool(typeof str === "string");
if (typeof str !== "string")
return;
this.writeUTF(str);
}
_advance(amount = 1) {
const before = this.size;
this._ensure(amount);
this.size += amount;
return before;
}
_ensure(size) {
if (this.bytes.byteLength < this.size + size) {
const bytes = new Uint8Array(this.size * 2);
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
bytes.set(this.bytes);
this.bytes = bytes;
this.view = view;
}
}
}
exports.DataWriter = DataWriter;