import { Collector } from "../collector/types.js"; import { createAsyncEqualityMap } from "../equality-map.js"; import { createAsyncEqualitySet } from "../equality-set.js"; import { createQueue } from "../queue.js"; import { getRandomElementAsync } from "../random/index.js"; import { AsyncRandomOptions } from "../random/types.js"; import { selectionSorter } from "../sorting.js"; import { Sequence } from "../sync/types.js"; import { MaybeAsyncAnyPredicate, MaybeAsyncConverter, MaybeAsyncEquater, MaybeAsyncBiConverter, MaybeAsyncAccumulator, MaybeAsyncComparer, MaybeAsyncAction, MaybePromiseLike, MaybeAsyncGenerator, MaybeAsyncSequence, MaybePromise } from "../types.js"; import { strictEquals, identity, operatorCompare, defaultArrayComparer, combineAsyncComparers, asAsyncIterable } from "../utils.js"; import { array, empty, wrap } from "./index.js"; import { AsyncSequence, AsyncSequencePipeline, GroupedAsyncSequence, OrderedAsyncSequence } from "./types.js"; export class AsyncSequenceMarker { } export abstract class BaseAsyncSequence extends AsyncSequenceMarker implements AsyncSequence { [Symbol.asyncIterator]() { return this.iterator(); } abstract iterator(): AsyncIterator; apply(pipeline: AsyncSequencePipeline): MaybePromise { return pipeline(this); } select(converter: MaybeAsyncConverter): AsyncSequence { return new SelectAsyncSequence(this, converter); } selectMany(converter: MaybeAsyncConverter>): AsyncSequence { return new SelectManyAsyncSequence(this, converter); } where(predicate: MaybeAsyncAnyPredicate): AsyncSequence { return new WhereAsyncSequence(this, predicate); } groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence>; groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence>; groupBy(keySelector: any, elementSelector?: any, keyComparer?: any) { return new GroupByAsyncSequence(this, keySelector, elementSelector, keyComparer); } join(sequence: MaybeAsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence<[TElement, TOther]>; join(sequence: MaybeAsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence; join(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return new JoinAsyncSequence(this, wrap(sequence), firstKeySelector, secondKeySelector, resultSelector, keyComparer); } groupJoin(sequence: MaybeAsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence>; groupJoin(sequence: MaybeAsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence; groupJoin(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return new GroupJoinAsyncSequence(this, wrap(sequence), firstKeySelector, secondKeySelector, resultSelector, keyComparer); } async contains(obj: TElement, equater?: MaybeAsyncEquater) { if (!equater) { equater = strictEquals; } for await (const element of this) { if (await equater(element, obj)) { return true; } } return false; } async sequenceEquals(sequence: MaybeAsyncSequence, equater?: MaybeAsyncEquater) { if (this === sequence) { return true; } const that = wrap(sequence); const thisCount = await this.nonEnumeratedCount(); const thatCount = await that.nonEnumeratedCount(); if (thisCount >= 0 && thatCount >= 0 && thisCount !== thatCount) { return false; } if (!equater) { equater = strictEquals; } const thisIterator = this.iterator(); const thatIterator = that.iterator(); while (true) { const thisNext = await thisIterator.next(); const thatNext = await thatIterator.next(); if (thisNext.done) { return thatNext.done === true; } if (thatNext.done) { return false; } if (!await equater(thisNext.value, thatNext.value)) { return false; } } } append(obj: TElement): AsyncSequence { return new AppendAsyncSequence(this, obj); } prepend(obj: TElement): AsyncSequence { return new PrependAsyncSequence(this, obj); } remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEquater): AsyncSequence { return new RemoveAsyncSequence(this, obj, all, equater); } concat(...sequences: MaybeAsyncSequence[]): AsyncSequence { if (sequences.length === 0) { return this; } const arr: AsyncSequence[] = [this]; for (const sequence of sequences) { arr.push(wrap(sequence)); } return new ConcatAsyncSequence(arr); } async count(predicate?: MaybeAsyncAnyPredicate) { let count = 0; if (predicate) { for await (const element of this) { if (await predicate(element)) { count++; } } } else { const iterator = this.iterator(); while (!(await iterator.next()).done) { count++; } } return count; } async nonEnumeratedCount() { return -1; } async fastCount() { const n = await this.nonEnumeratedCount(); return n >= 0 ? n : await this.count(); } async maxCount() { const n = await this.nonEnumeratedCount(); return n >= 0 ? n : Infinity; } async #tryGetFirst(predicate?: MaybeAsyncAnyPredicate) { if (predicate) { for await (const element of this) { if (await predicate(element)) { return { found: true, element } as const; } } } else { const next = await this.iterator().next(); if (!next.done) { return { found: true, element: next.value } as const; } } return { found: false } as const; } async first(predicate?: MaybeAsyncAnyPredicate) { const result = await this.#tryGetFirst(predicate); if (result.found) { return result.element; } throw new Error("No element was found."); } async firstOrDefault(predicate?: MaybeAsyncAnyPredicate, def?: TElement) { const result = await this.#tryGetFirst(predicate); return result.found ? result.element : def; } async #tryGetLast(predicate?: MaybeAsyncAnyPredicate) { let found = false; let result: TElement | undefined = undefined; if (predicate) { for await (const element of this) { if (await predicate(element)) { found = true; result = element; } } } else { for await (const element of this) { found = true; result = element; } } return { found, element: result }; } async last(predicate?: MaybeAsyncAnyPredicate) { const result = await this.#tryGetLast(predicate); if (result.found) { return result.element!; } throw new Error("No element was found."); } async lastOrDefault(predicate?: MaybeAsyncAnyPredicate, def?: TElement) { const result = await this.#tryGetLast(predicate); return result.found ? result.element : def; } async #tryGetSingle(predicate?: MaybeAsyncAnyPredicate) { if (predicate) { let result: { found: true; element: TElement; } | undefined = undefined; for await (const element of this) { if (await predicate(element)) { if (result) { return { found: false, reason: 2 } as const; } result = { found: true, element } as const; } } } else { const iterator = this.iterator(); let next = await iterator.next(); if (!next.done) { const result = { found: true, element: next.value } as const; next = await iterator.next(); if (next.done) { return result; } return { found: false, reason: 2 } as const; } } return { found: false, reason: 1 } as const; } async single(predicate?: MaybeAsyncAnyPredicate) { const result = await this.#tryGetSingle(predicate); if (result.found == true) { return result.element; } let reason: string; switch (result.reason) { case 1: reason = "No element was found."; break; case 2: reason = "More than one element was found."; break; default: reason = ""; } throw new Error(reason); } async singleOrDefault(predicate?: MaybeAsyncAnyPredicate, def?: TElement) { const result = await this.#tryGetSingle(predicate); return result.found ? result.element : def; } async #tryElementAt(index: number) { let i = index; for await (const element of this) { if (i === 0) { return { found: true, element } as const; } i--; } return { found: false } as const; } async elementAt(index: number) { const result = await this.#tryElementAt(index); if (result.found) { return result.element; } throw new Error("No element found at given index."); } async elementAtOrDefault(index: number, def?: TElement) { const result = await this.#tryElementAt(index); return result.found ? result.element : def; } async aggregate(accumulator: MaybeAsyncAccumulator, seed?: TAccumulator, resultSelector?: MaybeAsyncConverter) { const iterator = this.iterator(); if (seed === undefined) { const next = await iterator.next(); if (next.done) { throw new Error("Aggregation requires at least one element."); } seed = next.value as unknown as TAccumulator; } let acc = seed; while (true) { const next = await iterator.next(); if (next.done) { break; } acc = await accumulator(acc, next.value); } if (resultSelector) { return await resultSelector(acc); } return acc as unknown as TResult; } async #find(sorter: MaybeAsyncAnyPredicate, selector?: MaybeAsyncConverter, comparer?: MaybeAsyncComparer) { const iterator = this.iterator(); let next = await iterator.next(); if (next.done) { throw new Error("Sequence contains no element."); } if (!selector) { selector = identity as MaybeAsyncConverter; } if (!comparer) { comparer = operatorCompare; } let result = next.value; let convertedResult = await selector(result); while (true) { next = await iterator.next(); if (next.done) { break; } const value = next.value; const convertedValue = await selector(value); if (await sorter(await comparer(convertedResult, convertedValue))) { result = value; convertedResult = convertedValue; } } return result; } min(comparer?: MaybeAsyncComparer) { return this.#find(x => x > 0, undefined, comparer); } minBy(converter: MaybeAsyncConverter, comparer?: MaybeAsyncComparer) { return this.#find(x => x > 0, converter, comparer); } max(comparer?: MaybeAsyncComparer) { return this.#find(x => x < 0, undefined, comparer); } maxBy(converter: MaybeAsyncConverter, comparer?: MaybeAsyncComparer) { return this.#find(x => x < 0, converter, comparer); } order(comparer?: MaybeAsyncComparer): OrderedAsyncSequence { return new OrderAsyncSequence(this, false, comparer); } orderBy(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparer): OrderedAsyncSequence { return new OrderByAsyncSequence(this, false, selector, comparer); } orderDescending(comparer?: MaybeAsyncComparer): OrderedAsyncSequence { return new OrderAsyncSequence(this, true, comparer); } orderByDescending(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparer): OrderedAsyncSequence { return new OrderByAsyncSequence(this, true, selector, comparer); } partition(equater?: MaybeAsyncEquater): AsyncSequence> { return new PartitionAsyncSequence(this, equater); } partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater): AsyncSequence> { return new PartitionByAsyncSequence(this, selector, equater); } distinct(equater?: MaybeAsyncEquater): AsyncSequence { return new DistinctAsyncSequence(this, equater); } distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater): AsyncSequence { return new DistinctByAsyncSequence(this, selector, equater); } union(sequence: MaybeAsyncSequence, equater?: MaybeAsyncEquater): AsyncSequence { return new UnionAsyncSequence(this, wrap(sequence), equater); } unionBy(sequence: MaybeAsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater): AsyncSequence { return new UnionByAsyncSequence(this, wrap(sequence), selector, equater); } except(sequence: MaybeAsyncSequence): AsyncSequence { return new ExceptAsyncSequence(this, wrap(sequence)); } exceptBy(sequence: MaybeAsyncSequence, selector: MaybeAsyncConverter): AsyncSequence { return new ExceptByAsyncSequence(this, wrap(sequence), selector); } intersect(sequence: MaybeAsyncSequence): AsyncSequence { return new IntersectAsyncSequence(this, wrap(sequence)); } intersectBy(sequence: MaybeAsyncSequence, selector: MaybeAsyncConverter): AsyncSequence { return new IntersectByAsyncSequence(this, wrap(sequence), selector); } async all(predicate: MaybeAsyncAnyPredicate) { const n = await this.nonEnumeratedCount(); if (n === 0) { return false; } for await (const element of this) { if (!await predicate(element)) { return false; } } return true; } async any(predicate?: MaybeAsyncAnyPredicate) { const n = await this.nonEnumeratedCount(); if (n === 0) { return false; } if (predicate) { for await (const element of this) { if (await predicate(element)) { return true; } } return false; } return n < 0 ? !(await this.iterator().next()).done : n > 0; } async none(predicate?: MaybeAsyncAnyPredicate) { const n = await this.nonEnumeratedCount(); if (n === 0) { return true; } if (predicate) { for await (const element of this) { if (predicate(element)) { return false; } } return true; } return n < 0 && (await this.iterator().next()).done === true; } skip(n: number): AsyncSequence { if (n < 0) { throw new Error("Cannot skip a negative number of elements."); } return n === 0 ? this : new SkipAsyncSequence(this, n); } skipLast(n: number): AsyncSequence { if (n < 0) { throw new Error("Cannot skip a negative number of elements."); } return n === 0 ? this : new SkipLastAsyncSequence(this, n); } skipWhile(predicate: MaybeAsyncAnyPredicate): AsyncSequence { return new SkipWhileAsyncSequence(this, predicate); } take(n: number): AsyncSequence { if (n < 0) { throw new Error("Cannot take a negative number of elements."); } return n === 0 ? empty() : new TakeAsyncSequence(this, n); } takeLast(n: number): AsyncSequence { if (n < 0) { throw new Error("Cannot take a negative number of elements."); } return n === 0 ? empty() : new TakeLastAsyncSequence(this, n); } takeWhile(predicate: MaybeAsyncAnyPredicate): AsyncSequence { return new TakeWhileAsyncSequence(this, predicate); } peek(action: MaybeAsyncAction): AsyncSequence { return new PeekAsyncSequence(this, action); } async forEach(action: MaybeAsyncAction) { for await (const element of this) { await action(element); } } zip(sequence: MaybeAsyncSequence): AsyncSequence<[TElement, TOther]> { return new ZippedAsyncSequence(this, wrap(sequence)); } indexed(): AsyncSequence<[number, TElement]> { return new IndexedAsyncSequence(this); } reversed(): AsyncSequence { return new ReversedAsyncSequence(this); } chunked(size: number): AsyncSequence>; chunked(size: number, transformer: AsyncSequencePipeline): AsyncSequence; chunked(size: number, transformer?: AsyncSequencePipeline): AsyncSequence> | AsyncSequence { if (size <= 0) { throw new Error("Chunk size must be positive."); } const result = new ChunkedAsyncSequence(this, size); return transformer ? result.select(transformer) : result; } async random(options?: AsyncRandomOptions | undefined): Promise { return (await getRandomElementAsync(this, options)).element; } cached(): AsyncSequence { return new CacheAsyncSequence(this); } async asArray(): Promise { return await this.toArray(); } async toArray() { const array: TElement[] = []; for await (const element of this) { array.push(element); } return array; } toMap(keySelector: MaybeAsyncConverter): Promise>; toMap(keySelector: MaybeAsyncConverter, valueSelector: MaybeAsyncConverter): Promise>; async toMap(keySelector: MaybeAsyncConverter, valueSelector?: MaybeAsyncConverter): Promise> { valueSelector ??= identity; const map = new Map(); for await (const element of this) { const key = await keySelector(element); const value = await valueSelector(element); map.set(key, value); } return map; } async toSet() { const set = new Set(); for await (const element of this) { set.add(element); } return set; } toObject(keySelector: MaybeAsyncConverter): Promise>; toObject(keySelector: MaybeAsyncConverter, valueSelector: MaybeAsyncConverter): Promise>; async toObject(keySelector: MaybeAsyncConverter, valueSelector?: MaybeAsyncConverter): Promise> { valueSelector ??= identity; const obj: Record = {}; for await (const element of this) { const key = await keySelector(element); const value = await valueSelector(element); obj[key] = value; } return obj; } async collect(collector: Collector) { const acc = collector.initialize(); for await (const e of this) { collector.accumulate(acc, e); } return collector.finalize(acc); } } export class DelegatedAsyncSequence extends AsyncSequenceMarker implements AsyncSequence { #sequence: AsyncSequence; constructor(sequence: AsyncSequence) { super(); this.#sequence = sequence; } get sequence() { return this.#sequence; } [Symbol.asyncIterator]() { return this.iterator(); } iterator() { return this.#sequence.iterator(); } apply(pipeline: AsyncSequencePipeline) { return this.#sequence.apply(pipeline); } count(predicate?: MaybeAsyncAnyPredicate | undefined): Promise { return this.#sequence.count(predicate); } nonEnumeratedCount(): Promise { return this.#sequence.nonEnumeratedCount(); } fastCount(): Promise { return this.#sequence.fastCount(); } maxCount(): Promise { return this.#sequence.maxCount(); } select(selector: MaybeAsyncConverter): AsyncSequence { return this.#sequence.select(selector); } selectMany(selector: MaybeAsyncConverter>): AsyncSequence { return this.#sequence.selectMany(selector); } where(predicate: MaybeAsyncAnyPredicate): AsyncSequence { return this.#sequence.where(predicate); } groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence>; groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence>; groupBy(keySelector: any, elementSelector?: any, keyComparer?: any) { return this.#sequence.groupBy(keySelector, elementSelector, keyComparer); } join(sequence: MaybeAsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence<[TElement, TOther]>; join(sequence: MaybeAsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence; join(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return this.#sequence.join(sequence, firstKeySelector, secondKeySelector, resultSelector, keyComparer); } groupJoin(sequence: MaybeAsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence>; groupJoin(sequence: MaybeAsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEquater | undefined): AsyncSequence; groupJoin(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return this.#sequence.groupJoin(sequence, firstKeySelector, secondKeySelector, resultSelector, keyComparer); } contains(obj: TElement, equater?: MaybeAsyncEquater | undefined): Promise { return this.#sequence.contains(obj, equater); } sequenceEquals(sequence: MaybeAsyncSequence, equater?: MaybeAsyncEquater | undefined): Promise { return this.#sequence.sequenceEquals(sequence, equater); } append(obj: TElement): AsyncSequence { return this.#sequence.append(obj); } prepend(obj: TElement): AsyncSequence { return this.#sequence.prepend(obj); } remove(obj: TElement, all?: boolean | undefined, equater?: MaybeAsyncEquater | undefined): AsyncSequence { return this.#sequence.remove(obj, all, equater); } concat(...sequences: MaybeAsyncSequence[]): AsyncSequence { return this.#sequence.concat(...sequences); } first(predicate?: MaybeAsyncAnyPredicate | undefined): Promise { return this.#sequence.first(predicate); } firstOrDefault(predicate?: MaybeAsyncAnyPredicate | undefined, def?: TElement | undefined): Promise { return this.#sequence.firstOrDefault(predicate, def); } last(predicate?: MaybeAsyncAnyPredicate | undefined): Promise { return this.#sequence.last(predicate); } lastOrDefault(predicate?: MaybeAsyncAnyPredicate | undefined, def?: TElement | undefined): Promise { return this.#sequence.lastOrDefault(predicate, def); } single(predicate?: MaybeAsyncAnyPredicate | undefined): Promise { return this.#sequence.single(predicate); } singleOrDefault(predicate?: MaybeAsyncAnyPredicate | undefined, def?: TElement | undefined): Promise { return this.#sequence.singleOrDefault(predicate, def); } elementAt(index: number): Promise { return this.#sequence.elementAt(index); } elementAtOrDefault(index: number, def?: TElement | undefined): Promise { return this.#sequence.elementAtOrDefault(index, def); } aggregate(accumulator: MaybeAsyncAccumulator): Promise; aggregate(accumulator: MaybeAsyncAccumulator, seed?: TAccumulator | undefined): Promise; aggregate(accumulator: MaybeAsyncAccumulator, seed?: TAccumulator | undefined, resultSelector?: MaybeAsyncConverter | undefined): Promise; aggregate(accumulator: any, seed?: any, resultSelector?: any) { return this.#sequence.aggregate(accumulator, seed, resultSelector); } min(): Promise { return this.#sequence.min(); } minBy(selector: MaybeAsyncConverter): Promise { return this.#sequence.minBy(selector); } max(): Promise { return this.#sequence.max(); } maxBy(selector: MaybeAsyncConverter): Promise { return this.#sequence.maxBy(selector); } order(comparer?: MaybeAsyncComparer | undefined): AsyncSequence { return this.#sequence.order(comparer); } orderBy(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparer | undefined): AsyncSequence { return this.#sequence.orderBy(selector, comparer); } orderDescending(comparer?: MaybeAsyncComparer | undefined): AsyncSequence { return this.#sequence.orderDescending(comparer); } orderByDescending(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparer | undefined): AsyncSequence { return this.#sequence.orderByDescending(selector, comparer); } partition(equater?: MaybeAsyncEquater | undefined): AsyncSequence> { return this.#sequence.partition(equater); } partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater | undefined): AsyncSequence> { return this.#sequence.partitionBy(selector, equater); } distinct(equater?: MaybeAsyncEquater | undefined): AsyncSequence { return this.#sequence.distinct(equater); } distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater | undefined): AsyncSequence { return this.#sequence.distinctBy(selector, equater); } union(sequence: MaybeAsyncSequence, equater?: MaybeAsyncEquater | undefined): AsyncSequence { return this.#sequence.union(wrap(sequence), equater); } unionBy(sequence: MaybeAsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater | undefined): AsyncSequence { return this.#sequence.unionBy(wrap(sequence), selector, equater); } except(sequence: MaybeAsyncSequence, equater?: MaybeAsyncEquater | undefined): AsyncSequence { return this.#sequence.except(wrap(sequence), equater); } exceptBy(sequence: MaybeAsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater | undefined): AsyncSequence { return this.#sequence.exceptBy(wrap(sequence), selector, equater); } intersect(sequence: MaybeAsyncSequence, equater?: MaybeAsyncEquater | undefined): AsyncSequence { return this.#sequence.intersect(wrap(sequence), equater); } intersectBy(sequence: MaybeAsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater | undefined): AsyncSequence { return this.#sequence.intersectBy(wrap(sequence), selector, equater); } all(predicate: MaybeAsyncAnyPredicate): Promise { return this.#sequence.all(predicate); } any(predicate: MaybeAsyncAnyPredicate): Promise; any(): Promise; any(predicate?: any) { return this.#sequence.any(predicate); } none(predicate: MaybeAsyncAnyPredicate): Promise; none(): Promise; none(predicate?: any) { return this.#sequence.none(predicate); } skip(n: number): AsyncSequence { return this.#sequence.skip(n); } skipLast(n: number): AsyncSequence { return this.#sequence.skipLast(n); } skipWhile(condition: MaybeAsyncAnyPredicate): AsyncSequence { return this.#sequence.skipWhile(condition); } take(n: number): AsyncSequence { return this.#sequence.take(n); } takeLast(n: number): AsyncSequence { return this.#sequence.takeLast(n); } takeWhile(condition: MaybeAsyncAnyPredicate): AsyncSequence { return this.#sequence.takeWhile(condition); } peek(action: MaybeAsyncAction): AsyncSequence { return this.#sequence.peek(action); } forEach(action: MaybeAsyncAction): Promise { return this.#sequence.forEach(action); } zip(sequence: MaybeAsyncSequence): AsyncSequence<[TElement, TOther]> { return this.#sequence.zip(wrap(sequence)); } indexed(): AsyncSequence<[number, TElement]> { return this.#sequence.indexed(); } reversed(): AsyncSequence { return this.#sequence.reversed(); } chunked(size: number): AsyncSequence>; chunked(size: number, transformer: AsyncSequencePipeline): AsyncSequence; chunked(size: number, transformer?: any): any { return this.#sequence.chunked(size, transformer); } random(options?: AsyncRandomOptions | undefined): Promise { return this.#sequence.random(options); } cached(): AsyncSequence { return this.#sequence.cached(); } asArray(): Promise { return this.#sequence.asArray(); } toArray(): Promise { return this.#sequence.toArray(); } toMap(keySelector: MaybeAsyncConverter): Promise>; toMap(keySelector: MaybeAsyncConverter, valueSelector: MaybeAsyncConverter): Promise>; toMap(keySelector: any, valueSelector?: any) { return this.#sequence.toMap(keySelector, valueSelector); } toSet(): Promise> { return this.#sequence.toSet(); } toObject(keySelector: MaybeAsyncConverter): Promise>; toObject(keySelector: MaybeAsyncConverter, valueSelector: MaybeAsyncConverter): Promise>; toObject(keySelector: any, valueSelector?: any) { return this.#sequence.toObject(keySelector, valueSelector); } collect(collector: Collector): Promise { return this.#sequence.collect(collector); } } export class GroupedAsyncSequenceImpl extends DelegatedAsyncSequence implements GroupedAsyncSequence { readonly #key: TKey; constructor(key: TKey, grouping: AsyncSequence) { super(grouping); this.#key = key; } public get key() { return this.#key; } } abstract class BaseOrderedAsyncSequence extends BaseAsyncSequence implements OrderedAsyncSequence { readonly #sequence: AsyncSequence; readonly #sorter: MaybeAsyncComparer; readonly #descending: boolean; constructor(sequence: AsyncSequence, sorter: MaybeAsyncComparer, descending: boolean) { super(); this.#sequence = sequence; this.#sorter = sorter; this.#descending = descending; } override async nonEnumeratedCount() { return await this.#sequence.nonEnumeratedCount(); } override async maxCount() { return await this.#sequence.maxCount(); } get comparer() { return this.#sorter; } thenSelf(comparer?: MaybeAsyncComparer): OrderedAsyncSequence { return new ThenOrderAsyncSequence(this, false, comparer); } thenBy(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparer): OrderedAsyncSequence { return new ThenOrderByAsyncSequence(this, false, selector, comparer); } thenSelfDescending(comparer?: MaybeAsyncComparer): OrderedAsyncSequence { return new ThenOrderAsyncSequence(this, true, comparer); } thenByDescending(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparer): OrderedAsyncSequence { return new ThenOrderByAsyncSequence(this, true, selector, comparer); } override async *iterator() { const arr: TElement[] = []; for await (const obj of this.#sequence) { arr.push(obj); } await selectionSorter.sort(arr, this.#descending, this.#sorter); yield* arr; } } class EmptyAsyncSequence extends BaseAsyncSequence { override async nonEnumeratedCount() { return 0; } override async *iterator() { } } export const EMPTY = new EmptyAsyncSequence(); export class RangeAsyncSequence extends BaseAsyncSequence { readonly #min: number; readonly #max: number; readonly #step: number; constructor(min: number, max: number, step: number) { super(); this.#min = min; this.#max = max; this.#step = step; } override async nonEnumeratedCount() { return Math.ceil((this.#max - this.#min) / this.#step); } override async *iterator() { for (let i = this.#min; i < this.#max; i += this.#step) { yield i; } } } export class RepeatAsyncSequence extends BaseAsyncSequence { readonly #value: MaybePromiseLike; readonly #count: number; constructor(value: MaybePromiseLike, count: number) { super(); this.#value = value; this.#count = count; } override async nonEnumeratedCount() { return this.#count; } override async *iterator() { let i = this.#count; while (i-- > 0) { yield this.#value; } } } export class RepeatForeverAsyncSequence extends BaseAsyncSequence { readonly #value: MaybePromiseLike; constructor(value: MaybePromiseLike) { super(); this.#value = value; } override async nonEnumeratedCount() { return Infinity; } override async *iterator() { while (true) { yield this.#value; } } } export class WrappedObjectAsync extends BaseAsyncSequence { readonly #obj: MaybePromiseLike; constructor(obj: MaybePromiseLike) { super(); this.#obj = obj; } override async nonEnumeratedCount() { return 1; } override async *iterator() { yield this.#obj; } } export class WrappedArrayAsync extends BaseAsyncSequence { readonly #array: ReadonlyArray>; constructor(array: ReadonlyArray>) { super(); this.#array = array; } override async nonEnumeratedCount() { return this.#array.length; } override async *iterator() { yield* this.#array; } } export class WrappedArrayLikeAsync extends BaseAsyncSequence { readonly #arrayLike: ArrayLike>; constructor(arrayLike: ArrayLike>) { super(); this.#arrayLike = arrayLike; } override async nonEnumeratedCount() { return this.#arrayLike.length; } override async *iterator() { for (let i = 0; i < this.#arrayLike.length; i++) { yield this.#arrayLike[i]; } } } export class WrappedAsyncIterable extends BaseAsyncSequence { readonly #iterable: AsyncIterable>; constructor(iterable: AsyncIterable>) { super(); this.#iterable = iterable; } override async *iterator() { yield* this.#iterable; } } export class GeneratorAsyncSequence extends BaseAsyncSequence { readonly #generator: () => MaybeAsyncGenerator>; constructor(generator: () => MaybeAsyncGenerator>) { super(); this.#generator = generator; } override async *iterator() { yield* this.#generator(); } } export class FunctionAsyncSequence extends BaseAsyncSequence { readonly #f: () => MaybePromiseLike; constructor(f: () => MaybePromiseLike) { super(); this.#f = f; } override async nonEnumeratedCount() { return Infinity; } override async *iterator() { while (true) { yield await this.#f(); } } } export class WrappedSequence extends BaseAsyncSequence { readonly #sequence: Sequence>; constructor(sequence: Sequence>) { super(); this.#sequence = sequence; } override async nonEnumeratedCount() { return this.#sequence.nonEnumeratedCount(); } override async fastCount() { return this.#sequence.fastCount(); } override async maxCount() { return this.#sequence.maxCount(); } override async *iterator() { yield* this.#sequence; } } export class ConcatAsyncSequence extends BaseAsyncSequence { readonly #sequences: Iterable>; constructor(sequences: Iterable>) { super(); this.#sequences = sequences; } override async nonEnumeratedCount() { let n = 0; for (const sequence of this.#sequences) { const m = await sequence.nonEnumeratedCount(); if (m < 0) { return -1; } n += m; } return n; } override async *iterator() { for (const sequence of this.#sequences) { yield* sequence; } } } class DistinctAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #equater: MaybeAsyncEquater | undefined; constructor(sequence: AsyncSequence, equater?: MaybeAsyncEquater) { super(); this.#sequence = sequence; this.#equater = equater; } override async *iterator() { const set = createAsyncEqualitySet(this.#equater); for await (const obj of this.#sequence) { if (await set.add(obj)) { yield obj; } } } } class DistinctByAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #selector: MaybeAsyncConverter; readonly #equater: MaybeAsyncEquater | undefined; constructor(sequence: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater) { super(); this.#sequence = sequence; this.#selector = selector; this.#equater = equater; } override async *iterator() { const set = createAsyncEqualitySet(this.#equater); for await (const obj of this.#sequence) { if (await set.add(await this.#selector(obj))) { yield obj; } } set.clear(); } } class WhereAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #predicate: MaybeAsyncAnyPredicate; constructor(sequence: AsyncSequence, predicate: MaybeAsyncAnyPredicate) { super(); this.#sequence = sequence; this.#predicate = predicate; } override async *iterator() { for await (const obj of this.#sequence) { if (await this.#predicate(obj)) { yield obj; } } } } class SelectManyAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #converter: MaybeAsyncConverter>; constructor(sequence: AsyncSequence, converter: MaybeAsyncConverter>) { super(); this.#sequence = sequence; this.#converter = converter; } override async *iterator() { for await (const obj of this.#sequence) { yield* await this.#converter(obj); } } } class IndexedAsyncSequence extends BaseAsyncSequence<[number, T]> { readonly #sequence: AsyncSequence; constructor(sequence: AsyncSequence) { super(); this.#sequence = sequence; } override async *iterator() { let i = 0; for await (const obj of this.#sequence) { yield [i++, obj] as [number, T]; } } } class SelectAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #converter: MaybeAsyncConverter; constructor(sequence: AsyncSequence, converter: MaybeAsyncConverter) { super(); this.#sequence = sequence; this.#converter = converter; } override async nonEnumeratedCount() { return await this.#sequence.nonEnumeratedCount(); } override async *iterator() { for await (const obj of this.#sequence) { yield await this.#converter(obj); } } } class SkipWhileAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #predicate: MaybeAsyncAnyPredicate; constructor(sequence: AsyncSequence, predicate: MaybeAsyncAnyPredicate) { super(); this.#sequence = sequence; this.#predicate = predicate; } override async *iterator() { const iterator = this.#sequence.iterator(); while (true) { const next = await iterator.next(); if (next.done) { return; } if (await this.#predicate(next.value)) { continue; } yield next.value; break; } yield* asAsyncIterable(iterator); } } class SkipLastAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #n: number; constructor(sequence: AsyncSequence, n: number) { super(); this.#sequence = sequence; this.#n = n; } override async nonEnumeratedCount() { const n = await this.#sequence.nonEnumeratedCount(); return n < 0 ? -1 : Math.max(0, n - this.#n); } override async *iterator() { const iterator = this.#sequence.iterator(); const buffer = new Array(this.#n); // n > 0 let i = 0; do { const next = await iterator.next(); if (next.done) { return; } buffer[i++] = next.value; } while (i < this.#n); i = 0; for await (const obj of asAsyncIterable(iterator)) { yield buffer[i]; buffer[i] = obj; i = (i + 1) % this.#n; } } } class SkipAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #n: number; constructor(sequence: AsyncSequence, n: number) { super(); this.#sequence = sequence; this.#n = n; } override async nonEnumeratedCount() { const n = await this.#sequence.nonEnumeratedCount(); return n < 0 ? -1 : Math.max(0, n - this.#n); } override async *iterator() { const iterator = this.#sequence.iterator(); let i = 0; do { if ((await iterator.next()).done) { return; } i++; } while (i < this.#n); yield* asAsyncIterable(iterator); } } class TakeWhileAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #predicate: MaybeAsyncAnyPredicate; constructor(sequence: AsyncSequence, predicate: MaybeAsyncAnyPredicate) { super(); this.#sequence = sequence; this.#predicate = predicate; } override async *iterator() { for await (const obj of this.#sequence) { if (!await this.#predicate(obj)) { return; } yield obj; } } } class TakeLastAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #n: number; constructor(sequence: AsyncSequence, n: number) { super(); this.#sequence = sequence; this.#n = n; } override async nonEnumeratedCount() { const n = await this.#sequence.nonEnumeratedCount(); return n < 0 ? -1 : Math.min(this.#n, n); } override async *iterator() { const queue = createQueue(this.#n); for await (const obj of this.#sequence) { queue.enqueue(obj); } yield* queue; } } class TakeAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #n: number; constructor(sequence: AsyncSequence, n: number) { super(); this.#sequence = sequence; this.#n = n; } override async nonEnumeratedCount() { const n = await this.#sequence.nonEnumeratedCount(); return n < 0 ? -1 : Math.min(this.#n, n); } override async *iterator() { const iterator = this.#sequence.iterator(); let i = this.#n; while (i > 0) { const next = await iterator.next(); if (next.done) { return; } yield next.value as T; i--; } } } class OrderAsyncSequence extends BaseOrderedAsyncSequence { constructor(sequence: AsyncSequence, descending: boolean, sorter?: MaybeAsyncComparer) { super(sequence, sorter ?? defaultArrayComparer, descending); } } class OrderByAsyncSequence extends BaseOrderedAsyncSequence { constructor(sequence: AsyncSequence, descending: boolean, selector: MaybeAsyncConverter, sorter?: MaybeAsyncComparer) { super(sequence, OrderByAsyncSequence.#createSorter(selector, sorter), descending); } static #createSorter(selector: MaybeAsyncConverter, sorter?: MaybeAsyncComparer) { sorter ??= defaultArrayComparer; return async (a: T, b: T) => sorter(await selector(a), await selector(b)); } } class ThenOrderAsyncSequence extends BaseOrderedAsyncSequence { constructor(sequence: OrderedAsyncSequence, descending: boolean, sorter?: MaybeAsyncComparer) { super(sequence, combineAsyncComparers(sequence.comparer ?? defaultArrayComparer, sorter ?? defaultArrayComparer), descending); } } class ThenOrderByAsyncSequence extends BaseOrderedAsyncSequence { constructor(sequence: OrderedAsyncSequence, descending: boolean, selector: MaybeAsyncConverter, sorter?: MaybeAsyncComparer) { super(sequence, ThenOrderByAsyncSequence.#createCombinedSorter(sequence.comparer, selector, sorter), descending); } static #createCombinedSorter(baseSorter: MaybeAsyncComparer, selector: MaybeAsyncConverter, sorter?: MaybeAsyncComparer) { baseSorter ??= defaultArrayComparer; sorter ??= defaultArrayComparer; return combineAsyncComparers(baseSorter, async (a: T, b: T) => sorter(await selector(a), await selector(b))); } } class AppendAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #obj: T; constructor(sequence: AsyncSequence, obj: T) { super(); this.#sequence = sequence; this.#obj = obj; } override async nonEnumeratedCount() { const n = await this.#sequence.nonEnumeratedCount(); return n < 0 ? -1 : n + 1; } override async maxCount() { return await this.#sequence.maxCount() + 1; } override async *iterator() { yield* this.#sequence; yield this.#obj; } } class PrependAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #obj: T; constructor(sequence: AsyncSequence, obj: T) { super(); this.#sequence = sequence; this.#obj = obj; } override async nonEnumeratedCount() { const n = await this.#sequence.nonEnumeratedCount(); return n < 0 ? -1 : n + 1; } override async maxCount() { return await this.#sequence.maxCount() + 1; } override async *iterator() { yield this.#obj; yield* this.#sequence; } } class PeekAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #action: MaybeAsyncAction; constructor(sequence: AsyncSequence, action: MaybeAsyncAction) { super(); this.#sequence = sequence; this.#action = action; } override async *iterator() { for await (const obj of this.#sequence) { await this.#action(obj); yield obj; } } } class ZippedAsyncSequence extends BaseAsyncSequence<[T, U]> { readonly #first: AsyncSequence; readonly #second: AsyncSequence; constructor(first: AsyncSequence, second: AsyncSequence) { super(); this.#first = first; this.#second = second; } override async nonEnumeratedCount() { const first = await this.#first.nonEnumeratedCount(); const second = await this.#second.nonEnumeratedCount(); return first < 0 || second < 0 ? -1 : Math.min(first, second); } override async *iterator() { const firstIterator = this.#first.iterator(); const secondIterator = this.#second.iterator(); while (true) { const firstNext = await firstIterator.next(); const secondNext = await secondIterator.next(); if (firstNext.done || secondNext.done) { return; } yield [firstNext.value, secondNext.value] as [T, U]; } } } class UnionAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #equater: MaybeAsyncEquater | undefined; constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEquater) { super(); this.#first = first; this.#second = second; this.#equater = equater; } override async *iterator() { const set = createAsyncEqualitySet(this.#equater); for await (const obj of this.#first) { if (await set.add(obj)) { yield obj; } } for await (const obj of this.#second) { if (await set.add(obj)) { yield obj; } } set.clear(); } } class UnionByAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #selector: MaybeAsyncConverter; readonly #equater: MaybeAsyncEquater | undefined; constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater) { super(); this.#first = first; this.#second = second; this.#selector = selector; this.#equater = equater; } override async *iterator() { const set = createAsyncEqualitySet(this.#equater); for await (const obj of this.#first) { if (await set.add(await this.#selector(obj))) { yield obj; } } for await (const obj of this.#second) { if (await set.add(await this.#selector(obj))) { yield obj; } } set.clear(); } } class ExceptAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #equater: MaybeAsyncEquater | undefined; constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEquater) { super(); this.#first = first; this.#second = second; this.#equater = equater; } override async *iterator() { const set = createAsyncEqualitySet(this.#equater); for await (const obj of this.#second) { await set.add(obj); } for await (const obj of this.#first) { if (await set.add(obj)) { yield obj; } } set.clear(); } } class ExceptByAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #selector: MaybeAsyncConverter; readonly #equater: MaybeAsyncEquater | undefined; constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater) { super(); this.#first = first; this.#second = second; this.#selector = selector; this.#equater = equater; } override async *iterator() { const set = createAsyncEqualitySet(this.#equater); for await (const obj of this.#second) { await set.add(await this.#selector(obj)); } for await (const obj of this.#first) { if (await set.add(await this.#selector(obj))) { yield obj; } } set.clear(); } } class IntersectAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #equater: MaybeAsyncEquater | undefined; constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEquater) { super(); this.#first = first; this.#second = second; this.#equater = equater; } override async *iterator() { const set = createAsyncEqualitySet(this.#equater); for await (const obj of this.#second) { await set.add(obj); } for await (const obj of this.#first) { if (await set.remove(obj)) { yield obj; } } set.clear(); } } class IntersectByAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #selector: MaybeAsyncConverter; readonly #equater: MaybeAsyncEquater | undefined; constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEquater) { super(); this.#first = first; this.#second = second; this.#selector = selector; this.#equater = equater; } override async *iterator() { const set = createAsyncEqualitySet(this.#equater); for await (const obj of this.#second) { await set.add(await this.#selector(obj)); } for await (const obj of this.#first) { if (await set.remove(await this.#selector(obj))) { yield obj; } } set.clear(); } } class ReversedAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; constructor(sequence: AsyncSequence) { super(); this.#sequence = sequence; } override async *iterator() { const buffer: T[] = []; for await (const obj of this.#sequence) { buffer.push(obj); } for (let i = buffer.length - 1; i >= 0; i--) { yield buffer[i]; } } } class GroupByAsyncSequence extends BaseAsyncSequence> { readonly #sequence: AsyncSequence; readonly #keySelector: MaybeAsyncConverter; readonly #elementSelector: MaybeAsyncConverter; readonly #keyComparer: MaybeAsyncEquater | undefined; constructor(sequence: AsyncSequence, keySelector: MaybeAsyncConverter, elementSelector?: MaybeAsyncConverter, keyComparer?: MaybeAsyncEquater) { super(); this.#sequence = sequence; this.#keySelector = keySelector; this.#elementSelector = elementSelector ?? identity as MaybeAsyncConverter; this.#keyComparer = keyComparer; } override async *iterator() { const groupings = createAsyncEqualityMap(this.#keyComparer); for await (const obj of this.#sequence) { const key = await this.#keySelector(obj); const value = await this.#elementSelector(obj); const grouping = await groupings.get(key); if (grouping) { grouping.push(value); } else { await groupings.set(key, [value]); } } for (const entry of groupings) { yield new GroupedAsyncSequenceImpl(entry[0], array(entry[1])); } } } class ChunkedAsyncSequence extends BaseAsyncSequence> { readonly #sequence: AsyncSequence; readonly #size: number; constructor(sequence: AsyncSequence, size: number) { super(); this.#sequence = sequence; this.#size = size; } override async nonEnumeratedCount() { const n = await this.#sequence.nonEnumeratedCount(); return n < 0 ? -1 : Math.ceil(n / this.#size); } override async *iterator() { let chunk: T[] = []; for await (const obj of this.#sequence) { chunk.push(obj); if (chunk.length === this.#size) { yield array(chunk); chunk = []; } } if (chunk.length > 0) { yield array(chunk); } } } class JoinAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #firstKeySelector: MaybeAsyncConverter; readonly #secondKeySelector: MaybeAsyncConverter; readonly #resultSelector: MaybeAsyncBiConverter; readonly #keyComparer: MaybeAsyncEquater; constructor(first: AsyncSequence, second: AsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEquater) { super(); this.#first = first; this.#second = second; this.#firstKeySelector = firstKeySelector; this.#secondKeySelector = secondKeySelector; this.#resultSelector = resultSelector ?? identity as MaybeAsyncBiConverter; this.#keyComparer = keyComparer ?? strictEquals; } override async *iterator() { for await (const firstObj of this.#first) { const firstKey = await this.#firstKeySelector(firstObj); for await (const secondObj of this.#second) { const secondKey = await this.#secondKeySelector(secondObj); if (await this.#keyComparer(firstKey, secondKey)) { yield await this.#resultSelector(firstObj, secondObj); } } } } } class GroupJoinAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #firstKeySelector: MaybeAsyncConverter; readonly #secondKeySelector: MaybeAsyncConverter; readonly #resultSelector: MaybeAsyncBiConverter, TResult>; readonly #keyComparer: MaybeAsyncEquater; constructor(first: AsyncSequence, second: AsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEquater) { super(); this.#first = first; this.#second = second; this.#firstKeySelector = firstKeySelector; this.#secondKeySelector = secondKeySelector; this.#resultSelector = resultSelector ?? GroupJoinAsyncSequence.#defaultResultSelector as MaybeAsyncBiConverter, TResult>; this.#keyComparer = keyComparer ?? strictEquals; } static #defaultResultSelector(first: TOuter, second: AsyncSequence) { return new GroupedAsyncSequenceImpl(first, second); } override async *iterator() { for await (const firstObj of this.#first) { const firstKey = await this.#firstKeySelector(firstObj); const secondObjs: TInner[] = []; for await (const secondObj of this.#second) { const secondKey = await this.#secondKeySelector(secondObj); if (await this.#keyComparer(firstKey, secondKey)) { secondObjs.push(secondObj); } } // yield this.#resultSelector(firstObj, this.#second.where(secondObj => this.#keyComparer(firstKey, this.#secondKeySelector(secondObj)))); yield this.#resultSelector(firstObj, array(secondObjs)); } } } class RemoveAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #obj: T; readonly #all: boolean; readonly #equater: MaybeAsyncEquater; constructor(sequence: AsyncSequence, obj: T, all?: boolean, equater?: MaybeAsyncEquater) { super(); this.#sequence = sequence; this.#obj = obj; this.#all = all ?? false; this.#equater = equater ?? strictEquals; } override async *iterator() { let gotOne = false; for await (const obj of this.#sequence) { if (await this.#equater(this.#obj, obj)) { if (this.#all) { continue; } if (!gotOne) { gotOne = true; continue; } } yield obj; } } } class CacheAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; #cache: T[] | undefined; constructor(sequence: AsyncSequence) { super(); this.#sequence = sequence; } override async *iterator() { if (this.#cache) { yield* this.#cache; } else { const cache = []; for await (const e of this.#sequence) { cache.push(e); yield e; } this.#cache = cache; } } } class PartitionAsyncSequence extends BaseAsyncSequence> { readonly #sequence: AsyncSequence; readonly #equater: MaybeAsyncEquater; constructor(sequence: AsyncSequence, equater: MaybeAsyncEquater | undefined) { super(); this.#sequence = sequence; this.#equater = equater ?? strictEquals; } override async *iterator() { const partitions = createAsyncEqualityMap(this.#equater); for await (const obj of this.#sequence) { const partition = await partitions.get(obj); if (partition) { partition.push(obj); } else { await partitions.set(obj, [obj]); } } for (const partition of partitions.values()) { yield array(partition); } } } class PartitionByAsyncSequence extends BaseAsyncSequence> { readonly #sequence: AsyncSequence; readonly #selector: MaybeAsyncConverter; readonly #equater: MaybeAsyncEquater; constructor(sequence: AsyncSequence, selector: MaybeAsyncConverter, equater: MaybeAsyncEquater | undefined) { super(); this.#sequence = sequence; this.#selector = selector; this.#equater = equater ?? strictEquals; } override async *iterator() { const partitions = createAsyncEqualityMap(this.#equater); for await (const obj of this.#sequence) { const key = await this.#selector(obj); const partition = await partitions.get(key); if (partition) { partition.push(obj); } else { await partitions.set(key, [obj]); } } for (const partition of partitions.values()) { yield array(partition); } } }