import { Collector } from "../collector/types.js"; import { asAsyncComparer, combineAsyncComparers, createAsyncComparerUsing, defaultAsyncComparer } from "../comparer/async.js"; import { MaybeAsyncComparisonOrComparer, AsyncComparer } from "../comparer/types.js"; import { asAsyncEqualityComparer, defaultAsyncEqualityComparer } from "../equality-comparer/async.js"; import { AsyncEqualityComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { createAsyncEqualityMap } from "../equality-map/index.js"; import { createAsyncEqualitySet } from "../equality-set/index.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, MaybeAsyncBiConverter, MaybeAsyncAccumulator, MaybeAsyncAction, MaybePromiseLike, MaybeAsyncGenerator, MaybePromise, MaybeAsyncIterable, MaybeAsyncTypePredicate } from "../types.js"; import { asAsyncIterable, FindElementResult, identity } 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: MaybeAsyncTypePredicate): AsyncSequence; where(predicate: MaybeAsyncAnyPredicate): AsyncSequence; where(predicate: any) { return new WhereAsyncSequence(this, predicate); } groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; groupBy(keySelector: any, elementSelector?: any, keyComparer?: any) { return new GroupByAsyncSequence(this, keySelector, elementSelector, keyComparer); } join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence<[TElement, TOther]>; join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | 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: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | 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?: MaybeAsyncEqualityComparisonOrComparer) { equater = equater ? asAsyncEqualityComparer(equater) : defaultAsyncEqualityComparer; for await (const element of this) { if (await equater.equals(element, obj)) { return true; } } return false; } async sequenceEquals(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer) { 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; } equater = equater ? asAsyncEqualityComparer(equater) : defaultAsyncEqualityComparer; 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.equals(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?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new RemoveAsyncSequence(this, obj, all, equater); } concat(...sequences: MaybeAsyncIterable[]): 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): Promise> { if (predicate) { for await (const element of this) { if (await predicate(element)) { return { found: true, element }; } } } else { const next = await this.iterator().next(); if (!next.done) { return { found: true, element: next.value }; } } return { found: false }; } 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): Promise> { let result: FindElementResult = { found: false }; if (predicate) { for await (const element of this) { if (await predicate(element)) { result = { found: true, element }; } } } else { for await (const element of this) { result = { found: true, element }; } } return 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): Promise> { if (predicate) { let result: FindElementResult | undefined = undefined; for await (const element of this) { if (await predicate(element)) { if (result) { return { found: false, reason: 2 }; } result = { found: true, element }; } } } else { const iterator = this.iterator(); let next = await iterator.next(); if (!next.done) { const result: FindElementResult = { found: true, element: next.value }; next = await iterator.next(); if (next.done) { return result; } return { found: false, reason: 2 }; } } return { found: false, reason: 1 }; } async single(predicate?: MaybeAsyncAnyPredicate) { const result = await this.#tryGetSingle(predicate); if (result.found) { 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): Promise> { let i = index; for await (const element of this) { if (i === 0) { return { found: true, element }; } i--; } return { found: false }; } 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?: MaybeAsyncComparisonOrComparer) { 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; } comparer = comparer ? asAsyncComparer(comparer) : defaultAsyncComparer; 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.compare(convertedResult, convertedValue))) { result = value; convertedResult = convertedValue; } } return result; } min(comparer?: MaybeAsyncComparisonOrComparer) { return this.#find(x => x > 0, undefined, comparer); } minBy(converter: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer) { return this.#find(x => x > 0, converter, comparer); } max(comparer?: MaybeAsyncComparisonOrComparer) { return this.#find(x => x < 0, undefined, comparer); } maxBy(converter: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer) { return this.#find(x => x < 0, converter, comparer); } async #findBounds(selector?: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer): Promise<[min: TElement, max: TElement]> { 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; } comparer = comparer ? asAsyncComparer(comparer) : defaultAsyncComparer; let minBound = next.value, maxBound = minBound; let convertedMinBound = await selector(minBound), convertedMaxBound = convertedMinBound; while (true) { next = await iterator.next(); if (next.done) { break; } const value = next.value; const convertedValue = await selector(value); if (await comparer.compare(convertedMinBound, convertedValue) > 0) { minBound = value; convertedMinBound = convertedValue; } if (await comparer.compare(convertedMaxBound, convertedValue) < 0) { maxBound = value; convertedMaxBound = convertedValue; } } return [minBound, maxBound]; } bounds(comparer?: MaybeAsyncComparisonOrComparer) { return this.#findBounds(undefined, comparer); } boundsBy(converter: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer) { return this.#findBounds(converter, comparer); } order(comparer?: MaybeAsyncComparisonOrComparer): OrderedAsyncSequence { return new OrderAsyncSequence(this, false, comparer); } orderBy(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer): OrderedAsyncSequence { return new OrderByAsyncSequence(this, false, selector, comparer); } orderDescending(comparer?: MaybeAsyncComparisonOrComparer): OrderedAsyncSequence { return new OrderAsyncSequence(this, true, comparer); } orderByDescending(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer): OrderedAsyncSequence { return new OrderByAsyncSequence(this, true, selector, comparer); } partition(equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence> { return new PartitionAsyncSequence(this, equater); } partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence> { return new PartitionByAsyncSequence(this, selector, equater); } distinct(equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new DistinctAsyncSequence(this, equater); } distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new DistinctByAsyncSequence(this, selector, equater); } union(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new UnionAsyncSequence(this, wrap(sequence), equater); } unionBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new UnionByAsyncSequence(this, wrap(sequence), selector, equater); } except(sequence: MaybeAsyncIterable): AsyncSequence { return new ExceptAsyncSequence(this, wrap(sequence)); } exceptBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter): AsyncSequence { return new ExceptByAsyncSequence(this, wrap(sequence), selector); } intersect(sequence: MaybeAsyncIterable): AsyncSequence { return new IntersectAsyncSequence(this, wrap(sequence)); } intersectBy(sequence: MaybeAsyncIterable, 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: MaybeAsyncIterable): AsyncSequence<[TElement, TOther]> { return new ZippedAsyncSequence(this, wrap(sequence)); } cartesianProduct(sequence: MaybeAsyncIterable): AsyncSequence<[TElement, TOther]> { return new CartesianProductAsyncSequence(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() { return await Array.fromAsync(this); } async toArray() { return await Array.fromAsync(this); } 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: MaybeAsyncTypePredicate): AsyncSequence; where(predicate: MaybeAsyncAnyPredicate): AsyncSequence; where(predicate: any) { return this.#sequence.where(predicate); } groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; groupBy(keySelector: any, elementSelector?: any, keyComparer?: any) { return this.#sequence.groupBy(keySelector, elementSelector, keyComparer); } join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence<[TElement, TOther]>; join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence; join(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return this.#sequence.join(sequence, firstKeySelector, secondKeySelector, resultSelector, keyComparer); } groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | 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?: MaybeAsyncEqualityComparisonOrComparer | undefined): Promise { return this.#sequence.contains(obj, equater); } sequenceEquals(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer | 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?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.remove(obj, all, equater); } concat(...sequences: MaybeAsyncIterable[]): 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); } bounds(comparer?: MaybeAsyncComparisonOrComparer | undefined): Promise<[min: TElement, max: TElement]> { return this.#sequence.bounds(comparer); } boundsBy(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer | undefined): Promise<[min: TElement, max: TElement]> { return this.#sequence.boundsBy(selector, comparer); } order(comparer?: MaybeAsyncComparisonOrComparer | undefined): OrderedAsyncSequence { return this.#sequence.order(comparer); } orderBy(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer | undefined): OrderedAsyncSequence { return this.#sequence.orderBy(selector, comparer); } orderDescending(comparer?: MaybeAsyncComparisonOrComparer | undefined): OrderedAsyncSequence { return this.#sequence.orderDescending(comparer); } orderByDescending(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer | undefined): OrderedAsyncSequence { return this.#sequence.orderByDescending(selector, comparer); } partition(equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence> { return this.#sequence.partition(equater); } partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence> { return this.#sequence.partitionBy(selector, equater); } distinct(equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.distinct(equater); } distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.distinctBy(selector, equater); } union(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.union(wrap(sequence), equater); } unionBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.unionBy(wrap(sequence), selector, equater); } except(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.except(wrap(sequence), equater); } exceptBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.exceptBy(wrap(sequence), selector, equater); } intersect(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.intersect(wrap(sequence), equater); } intersectBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | 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: MaybeAsyncIterable): AsyncSequence<[TElement, TOther]> { return this.#sequence.zip(wrap(sequence)); } cartesianProduct(sequence: MaybeAsyncIterable): AsyncSequence<[TElement, TOther]> { return this.#sequence.cartesianProduct(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: AsyncComparer; readonly #descending: boolean; constructor(sequence: AsyncSequence, sorter: MaybeAsyncComparisonOrComparer | undefined, descending: boolean) { super(); this.#sequence = sequence; this.#sorter = sorter ? asAsyncComparer(sorter) : defaultAsyncComparer; 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?: MaybeAsyncComparisonOrComparer): OrderedAsyncSequence { return new ThenOrderAsyncSequence(this, false, comparer); } thenBy(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer): OrderedAsyncSequence { return new ThenOrderByAsyncSequence(this, false, selector, comparer); } thenSelfDescending(comparer?: MaybeAsyncComparisonOrComparer): OrderedAsyncSequence { return new ThenOrderAsyncSequence(this, true, comparer); } thenByDescending(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer): OrderedAsyncSequence { return new ThenOrderByAsyncSequence(this, true, selector, comparer); } override async *iterator() { const arr = await Array.fromAsync(this.#sequence); 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 WrappedPromise extends BaseAsyncSequence { readonly #promise: Promise>; constructor(promise: Promise>) { super(); this.#promise = promise; } override async *iterator() { yield* await this.#promise; } } 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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(sequence: AsyncSequence, equater?: MaybeAsyncEqualityComparisonOrComparer) { 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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(sequence: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer) { 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: MaybeAsyncTypePredicate; constructor(sequence: AsyncSequence, predicate: MaybeAsyncTypePredicate) { super(); this.#sequence = sequence; this.#predicate = predicate; } override async *iterator() { for await (const obj of this.#sequence) { if (await this.#predicate(obj)) { yield obj as TFiltered; } } } } 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; i--; } } } class OrderAsyncSequence extends BaseOrderedAsyncSequence { constructor(sequence: AsyncSequence, descending: boolean, sorter?: MaybeAsyncComparisonOrComparer) { super(sequence, sorter, descending); } } class OrderByAsyncSequence extends BaseOrderedAsyncSequence { constructor(sequence: AsyncSequence, descending: boolean, selector: MaybeAsyncConverter, sorter?: MaybeAsyncComparisonOrComparer) { super(sequence, createAsyncComparerUsing(selector, sorter), descending); } } class ThenOrderAsyncSequence extends BaseOrderedAsyncSequence { constructor(sequence: OrderedAsyncSequence, descending: boolean, sorter?: MaybeAsyncComparisonOrComparer) { super(sequence, combineAsyncComparers([sequence.comparer, sorter]), descending); } } class ThenOrderByAsyncSequence extends BaseOrderedAsyncSequence { constructor(sequence: OrderedAsyncSequence, descending: boolean, selector: MaybeAsyncConverter, sorter?: MaybeAsyncComparisonOrComparer) { super(sequence, combineAsyncComparers([sequence.comparer, createAsyncComparerUsing(selector, sorter)]), descending); } } 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]; } } } export class CartesianProductAsyncSequence 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 n1 = await this.#first.nonEnumeratedCount(); if (n1 < 0) { return -1; } const n2 = await this.#second.nonEnumeratedCount(); if (n2 < 0) { return -1; } return n1 * n2; } override async maxCount() { return await this.#first.maxCount() * await this.#second.maxCount(); } override async *iterator() { for await (const firstObj of this.#first) { for await (const secondObj of this.#second) { yield [firstObj, secondObj] as [T, U]; } } } } class UnionAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEqualityComparisonOrComparer) { 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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer) { 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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEqualityComparisonOrComparer) { 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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer) { 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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEqualityComparisonOrComparer) { 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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer) { 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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(sequence: AsyncSequence, keySelector: MaybeAsyncConverter, elementSelector?: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer) { 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: AsyncEqualityComparer; constructor(first: AsyncSequence, second: AsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; this.#second = second; this.#firstKeySelector = firstKeySelector; this.#secondKeySelector = secondKeySelector; this.#resultSelector = resultSelector ?? identity as MaybeAsyncBiConverter; this.#keyComparer = keyComparer ? asAsyncEqualityComparer(keyComparer) : defaultAsyncEqualityComparer; } 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.equals(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: AsyncEqualityComparer; constructor(first: AsyncSequence, second: AsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; this.#second = second; this.#firstKeySelector = firstKeySelector; this.#secondKeySelector = secondKeySelector; this.#resultSelector = resultSelector ?? GroupJoinAsyncSequence.#defaultResultSelector as MaybeAsyncBiConverter, TResult>; this.#keyComparer = keyComparer ? asAsyncEqualityComparer(keyComparer) : defaultAsyncEqualityComparer; } 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.equals(firstKey, secondKey)) { secondObjs.push(secondObj); } } yield this.#resultSelector(firstObj, array(secondObjs)); } } } class RemoveAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #obj: T; readonly #all: boolean; readonly #equater: AsyncEqualityComparer; constructor(sequence: AsyncSequence, obj: T, all?: boolean, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#sequence = sequence; this.#obj = obj; this.#all = all ?? false; this.#equater = equater ? asAsyncEqualityComparer(equater) : defaultAsyncEqualityComparer; } override async *iterator() { let gotOne = false; for await (const obj of this.#sequence) { if (await this.#equater.equals(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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(sequence: AsyncSequence, equater: MaybeAsyncEqualityComparisonOrComparer | undefined) { super(); this.#sequence = sequence; this.#equater = equater; } 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: MaybeAsyncEqualityComparisonOrComparer | undefined; constructor(sequence: AsyncSequence, selector: MaybeAsyncConverter, equater: MaybeAsyncEqualityComparisonOrComparer | undefined) { super(); this.#sequence = sequence; this.#selector = selector; this.#equater = equater; } 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); } } }