import { copyBytes } from "./deps.ts";
export class PacketWriter { private size: number; private buffer: Uint8Array; private offset: number; private headerPosition: number; private encoder = new TextEncoder();
constructor(size?: number) { this.size = size || 1024; this.buffer = new Uint8Array(this.size + 5); this.offset = 5; this.headerPosition = 0; }
_ensure(size: number) { const remaining = this.buffer.length - this.offset; if (remaining < size) { const oldBuffer = this.buffer; const newSize = oldBuffer.length + (oldBuffer.length >> 1) + size; this.buffer = new Uint8Array(newSize); copyBytes(oldBuffer, this.buffer); } }
addInt32(num: number) { this._ensure(4); this.buffer[this.offset++] = (num >>> 24) & 0xff; this.buffer[this.offset++] = (num >>> 16) & 0xff; this.buffer[this.offset++] = (num >>> 8) & 0xff; this.buffer[this.offset++] = (num >>> 0) & 0xff; return this; }
addInt16(num: number) { this._ensure(2); this.buffer[this.offset++] = (num >>> 8) & 0xff; this.buffer[this.offset++] = (num >>> 0) & 0xff; return this; }
addCString(string?: string) { if (!string) { this._ensure(1); } else { const encodedStr = this.encoder.encode(string); this._ensure(encodedStr.byteLength + 1); copyBytes(encodedStr, this.buffer, this.offset); this.offset += encodedStr.byteLength; }
this.buffer[this.offset++] = 0; return this; }
addChar(c: string) { if (c.length != 1) { throw new Error("addChar requires single character strings"); }
this._ensure(1); copyBytes(this.encoder.encode(c), this.buffer, this.offset); this.offset++; return this; }
addString(string?: string) { string = string || ""; const encodedStr = this.encoder.encode(string); this._ensure(encodedStr.byteLength); copyBytes(encodedStr, this.buffer, this.offset); this.offset += encodedStr.byteLength; return this; }
add(otherBuffer: Uint8Array) { this._ensure(otherBuffer.length); copyBytes(otherBuffer, this.buffer, this.offset); this.offset += otherBuffer.length; return this; }
clear() { this.offset = 5; this.headerPosition = 0; }
addHeader(code: number, last?: boolean) { const origOffset = this.offset; this.offset = this.headerPosition; this.buffer[this.offset++] = code; this.addInt32(origOffset - (this.headerPosition + 1)); this.headerPosition = origOffset; this.offset = origOffset; if (!last) { this._ensure(5); this.offset += 5; } return this; }
join(code?: number) { if (code) { this.addHeader(code, true); } return this.buffer.slice(code ? 0 : 5, this.offset); }
flush(code?: number) { const result = this.join(code); this.clear(); return result; }}