import { copy } from "../bytes/copy.ts";import type { Writer, WriterSync } from "../types.d.ts";
const DEFAULT_BUF_SIZE = 4096;
abstract class AbstractBufBase { buf: Uint8Array; usedBufferBytes = 0; err: Error | null = null;
constructor(buf: Uint8Array) { this.buf = buf; }
size(): number { return this.buf.byteLength; }
available(): number { return this.buf.byteLength - this.usedBufferBytes; }
buffered(): number { return this.usedBufferBytes; }}
export class BufWriter extends AbstractBufBase implements Writer { #writer: Writer;
static create(writer: Writer, size: number = DEFAULT_BUF_SIZE): BufWriter { return writer instanceof BufWriter ? writer : new BufWriter(writer, size); }
constructor(writer: Writer, size: number = DEFAULT_BUF_SIZE) { super(new Uint8Array(size <= 0 ? DEFAULT_BUF_SIZE : size)); this.#writer = writer; }
reset(w: Writer) { this.err = null; this.usedBufferBytes = 0; this.#writer = w; }
async flush() { if (this.err !== null) throw this.err; if (this.usedBufferBytes === 0) return;
try { const p = this.buf.subarray(0, this.usedBufferBytes); let nwritten = 0; while (nwritten < p.length) { nwritten += await this.#writer.write(p.subarray(nwritten)); } } catch (e) { if (e instanceof Error) { this.err = e; } throw e; }
this.buf = new Uint8Array(this.buf.length); this.usedBufferBytes = 0; }
async write(data: Uint8Array): Promise<number> { if (this.err !== null) throw this.err; if (data.length === 0) return 0;
let totalBytesWritten = 0; let numBytesWritten = 0; while (data.byteLength > this.available()) { if (this.buffered() === 0) { try { numBytesWritten = await this.#writer.write(data); } catch (e) { if (e instanceof Error) { this.err = e; } throw e; } } else { numBytesWritten = copy(data, this.buf, this.usedBufferBytes); this.usedBufferBytes += numBytesWritten; await this.flush(); } totalBytesWritten += numBytesWritten; data = data.subarray(numBytesWritten); }
numBytesWritten = copy(data, this.buf, this.usedBufferBytes); this.usedBufferBytes += numBytesWritten; totalBytesWritten += numBytesWritten; return totalBytesWritten; }}
export class BufWriterSync extends AbstractBufBase implements WriterSync { #writer: WriterSync;
static create( writer: WriterSync, size: number = DEFAULT_BUF_SIZE, ): BufWriterSync { return writer instanceof BufWriterSync ? writer : new BufWriterSync(writer, size); }
constructor(writer: WriterSync, size: number = DEFAULT_BUF_SIZE) { super(new Uint8Array(size <= 0 ? DEFAULT_BUF_SIZE : size)); this.#writer = writer; }
reset(w: WriterSync) { this.err = null; this.usedBufferBytes = 0; this.#writer = w; }
flush() { if (this.err !== null) throw this.err; if (this.usedBufferBytes === 0) return;
try { const p = this.buf.subarray(0, this.usedBufferBytes); let nwritten = 0; while (nwritten < p.length) { nwritten += this.#writer.writeSync(p.subarray(nwritten)); } } catch (e) { if (e instanceof Error) { this.err = e; } throw e; }
this.buf = new Uint8Array(this.buf.length); this.usedBufferBytes = 0; }
writeSync(data: Uint8Array): number { if (this.err !== null) throw this.err; if (data.length === 0) return 0;
let totalBytesWritten = 0; let numBytesWritten = 0; while (data.byteLength > this.available()) { if (this.buffered() === 0) { try { numBytesWritten = this.#writer.writeSync(data); } catch (e) { if (e instanceof Error) { this.err = e; } throw e; } } else { numBytesWritten = copy(data, this.buf, this.usedBufferBytes); this.usedBufferBytes += numBytesWritten; this.flush(); } totalBytesWritten += numBytesWritten; data = data.subarray(numBytesWritten); }
numBytesWritten = copy(data, this.buf, this.usedBufferBytes); this.usedBufferBytes += numBytesWritten; totalBytesWritten += numBytesWritten; return totalBytesWritten; }}