import {Collection} from './Collection.ts' export type MaybeIterationItem = { done: boolean, value?: T } export type ChunkCallback = (items: Collection) => any export class StopIteration extends Error {} export abstract class Iterable { protected index = 0 abstract async at_index(i: number): Promise abstract async from_range(start: number, end: number): Promise> abstract async count(): Promise abstract clone(): Iterable public async next(): Promise> { const i = this.index if ( i >= await this.count() ) { return { done: true } } this.index = i + 1 return { done: false, value: await this.at_index(i) } } [Symbol.asyncIterator]() { return this } public async chunk(size: number, callback: ChunkCallback) { const total = await this.count() while ( this.index < total ) { const items = await this.from_range(this.index, this.index + size - 1) try { await callback(items) } catch ( error ) { if ( error instanceof StopIteration ) break else throw error } this.index += size } } public async seek(index: number) { if ( index < 0 ) throw new TypeError('Cannot seek to negative index.') else if ( index >= await this.count() ) throw new TypeError('Cannot seek past last item.') this.index = index } public async peek(): Promise { if ( this.index + 1 >= await this.count() ) return undefined else return this.at_index(this.index + 1) } public async reset() { this.index = 0 } }