import {BusyBufferDeserializerError} from '../error/busy-buffer-deserializer-error.js'; import type {Decoding} from '../type/decoding.js'; import {isYield} from '../util/guard/is-yield.js'; import {BufferReaderController} from './buffer-reader-controller.js'; import type {BufferReaderGenerator} from './buffer-reader-generator.js'; import type {BufferSourceReaderFlush} from './buffer-source-reader-flush.js'; export class BufferSourceStreamReader { public static from( stream: ReadableStream, ): BufferSourceStreamReader { return new BufferSourceStreamReader(stream.getReader()); } #busy = false; readonly #controller = new BufferReaderController(); readonly #reader: ReadableStreamDefaultReader; public constructor(reader: ReadableStreamDefaultReader) { this.#reader = reader; } async #handle(generator: BufferReaderGenerator): Promise { if (this.#busy) { throw new BusyBufferDeserializerError(); } this.#busy = true; let result: IteratorResult = generator.next(); while (isYield(result)) { result = generator.next(await this.#reader.read()); } this.#busy = false; return result.value; } public async final(flush?: boolean): Promise { // eslint-disable-next-line @typescript-eslint/no-invalid-void-type await this.#handle(this.#controller.final(flush)); this.#reader.releaseLock(); } public async finalRead( decoding: Decoding, flush: BufferSourceReaderFlush = () => false, ): Promise { const result: T = await this.read(decoding); await this.final(flush(result)); return result; } public read(decoding: Decoding): Promise { return this.#handle(this.#controller.read(decoding)); } }