export interface StringBuilder { byteLength: number appendChar: (char: number) => void appendBuf: (buf: Uint8Array, start?: number, end?: number) => void reset: () => void toString: () => string } export class NonBufferedString implements StringBuilder { private decoder = new TextDecoder('utf-8') private string = '' public byteLength = 0 public appendChar(char: number): void { this.string += String.fromCharCode(char) this.byteLength += 1 } public appendBuf(buf: Uint8Array, start = 0, end: number = buf.length): void { this.string += this.decoder.decode(buf.subarray(start, end)) this.byteLength += end - start } public reset(): void { this.string = '' this.byteLength = 0 } public toString(): string { return this.string } } export class BufferedString implements StringBuilder { private decoder = new TextDecoder('utf-8') private buffer: Uint8Array private bufferOffset = 0 private string = '' public byteLength = 0 public constructor(bufferSize: number) { this.buffer = new Uint8Array(bufferSize) } public appendChar(char: number): void { if (this.bufferOffset >= this.buffer.length) this.flushStringBuffer() this.buffer[this.bufferOffset++] = char this.byteLength += 1 } public appendBuf(buf: Uint8Array, start = 0, end: number = buf.length): void { const size = end - start if (this.bufferOffset + size > this.buffer.length) this.flushStringBuffer() this.buffer.set(buf.subarray(start, end), this.bufferOffset) this.bufferOffset += size this.byteLength += size } private flushStringBuffer(): void { this.string += this.decoder.decode(this.buffer.subarray(0, this.bufferOffset)) this.bufferOffset = 0 } public reset(): void { this.string = '' this.bufferOffset = 0 this.byteLength = 0 } public toString(): string { this.flushStringBuffer() return this.string } }