import { ASYNC_ITERATOR_CONSTRUCTOR, PROMISE_CONSTRUCTOR, STREAM_CONSTRUCTOR, } from './constructors'; import { SYM_ASYNC_ITERATOR } from './symbols'; export interface StreamListener { next(value: T): void; throw(value: unknown): void; return(value: T): void; } export interface Stream { __SEROVAL_STREAM__: true; on(listener: StreamListener): () => void; next(value: T): void; throw(value: unknown): void; return(value: T): void; } export function isStream(value: object): value is Stream { return '__SEROVAL_STREAM__' in value; } export function createStream(): Stream { return STREAM_CONSTRUCTOR() as unknown as Stream; } export function createStreamFromAsyncIterable( iterable: AsyncIterable, ): Stream { const stream = createStream(); const iterator = iterable[SYM_ASYNC_ITERATOR](); async function push(): Promise { try { const value = await iterator.next(); if (value.done) { stream.return(value.value as T); } else { stream.next(value.value); await push(); } } catch (error) { stream.throw(error); } } push().catch(() => { // no-op }); return stream; } const createAsyncIterable = ASYNC_ITERATOR_CONSTRUCTOR( SYM_ASYNC_ITERATOR, PROMISE_CONSTRUCTOR, ); export function streamToAsyncIterable( stream: Stream, ): () => AsyncIterableIterator { return createAsyncIterable( stream, ) as unknown as () => AsyncIterableIterator; }