@rimbu/stream
Version:
Efficient structure representing a sequence of elements, with powerful operations for TypeScript
654 lines • 23.7 kB
JavaScript
var _AsyncReduceIterator_instance, _AsyncTransformerFastIterator_done, _AsyncTransformerFastIterator_instance, _AsyncTransformerFastIterator_currentValues;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
import { Token } from '@rimbu/base';
import { AsyncOptLazy, CollectFun, TraverseState, } from '@rimbu/common';
import { AsyncTransformer, } from '@rimbu/stream/async';
import { closeIters, fromAsyncStreamSource, } from '@rimbu/stream/async-custom';
/**
* A frozen `IteratorResult` that represents the completed asynchronous iterator state.
* This value is reused to avoid repeated allocations in async iterator implementations.
*/
export const fixedDoneAsyncIteratorResult = Object.freeze(Promise.resolve(Object.freeze({
done: true,
value: undefined,
})));
/**
* Returns true if the given `iterator` implements the `AsyncFastIterator` interface.
* @param iterator - the async iterator instance to test
*/
export function isAsyncFastIterator(iterator) {
return `fastNext` in iterator;
}
/**
* An `AsyncFastIterator` that is already exhausted and never yields values.
* Its `fastNext` method always resolves to the provided fallback value.
*/
export const emptyAsyncFastIterator = Object.freeze({
fastNext(otherwise) {
return AsyncOptLazy.toMaybePromise(otherwise);
},
next() {
return fixedDoneAsyncIteratorResult;
},
});
/**
* Base class for asynchronous fast iterators that implements `next` in terms of `fastNext`.
* Subclasses only need to implement the `fastNext` method.
*/
export class AsyncFastIteratorBase {
async next() {
const done = Symbol('Done');
const value = await this.fastNext(done);
if (done === value)
return fixedDoneAsyncIteratorResult;
return { value, done: false };
}
}
export class AsyncOfIterator extends AsyncFastIteratorBase {
constructor(values) {
super();
this.values = values;
this.index = 0;
}
fastNext(otherwise) {
const index = this.index;
const values = this.values;
if (index >= values.length)
return AsyncOptLazy.toMaybePromise(otherwise);
return AsyncOptLazy.toMaybePromise(values[this.index++]);
}
}
export class FromResourceIterator extends AsyncFastIteratorBase {
constructor(open, createSource, close, asyncStreamSourceHelpers) {
super();
this.open = open;
this.createSource = createSource;
this.close = close;
this.asyncStreamSourceHelpers = asyncStreamSourceHelpers;
this.return = async () => {
if (close && this.resource) {
await close(this.resource);
this.resource = undefined;
}
await this.iterator?.return?.();
this.return = undefined;
};
}
async fastNext(otherwise) {
if (undefined === this.iterator) {
const resource = await this.open();
this.resource = resource;
const source = await this.createSource(resource);
this.iterator = this.asyncStreamSourceHelpers
.fromAsyncStreamSource(source)[Symbol.asyncIterator]();
}
try {
return await this.iterator.fastNext(async () => {
if (undefined !== this.return) {
await this.return();
}
return AsyncOptLazy.toMaybePromise(otherwise);
});
}
catch (err) {
if (undefined !== this.return) {
await this.return();
}
throw err;
}
}
}
export class AsyncUnfoldIterator extends AsyncFastIteratorBase {
constructor(init, getNext) {
super();
this.getNext = getNext;
this.index = 0;
this.current = init;
}
async fastNext(otherwise) {
const current = this.current;
if (Token === current)
return AsyncOptLazy.toMaybePromise(otherwise);
if (this.index === 0) {
this.index++;
return current;
}
const next = await this.getNext(current, this.index++, Token);
this.current = next;
if (Token === next)
return AsyncOptLazy.toMaybePromise(otherwise);
return next;
}
}
export class AsyncZipWithIterator extends AsyncFastIteratorBase {
constructor(iterables, zipFun, asyncStreamSourceHelpers) {
super();
this.iterables = iterables;
this.zipFun = zipFun;
this.asyncStreamSourceHelpers = asyncStreamSourceHelpers;
this.sources = iterables.map((source) => this.asyncStreamSourceHelpers
.fromAsyncStreamSource(source)[Symbol.asyncIterator]());
this.sourcesToClose = new Set(this.sources);
this.return = () => closeIters(...this.sourcesToClose);
}
async fastNext(otherwise) {
const sources = this.sources;
const done = Symbol('Done');
const result = await Promise.all(sources.map((source) => source.fastNext(() => {
this.sourcesToClose.delete(source);
return done;
})));
if (this.sourcesToClose.size !== sources.length) {
await closeIters(this);
return AsyncOptLazy.toMaybePromise(otherwise);
}
return this.zipFun(...result);
}
}
export class AsyncZipAllWithItererator extends AsyncFastIteratorBase {
constructor(fillValue, iters, zipFun, asyncStreamSourceHelpers) {
super();
this.fillValue = fillValue;
this.iters = iters;
this.zipFun = zipFun;
this.asyncStreamSourceHelpers = asyncStreamSourceHelpers;
this.sources = iters.map((o) => this.asyncStreamSourceHelpers
.fromAsyncStreamSource(o)[Symbol.asyncIterator]());
this.sourcesToClose = new Set(this.sources);
this.return = () => closeIters(...this.sourcesToClose);
}
async fastNext(otherwise) {
if (this.sourcesToClose.size === 0) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
const sources = this.sources;
const fillValue = this.fillValue;
const result = await Promise.all(sources.map((source) => {
if (this.sourcesToClose.has(source)) {
return source.fastNext(() => {
this.sourcesToClose.delete(source);
return AsyncOptLazy.toMaybePromise(fillValue);
});
}
return AsyncOptLazy.toMaybePromise(fillValue);
}));
if (this.sourcesToClose.size === 0) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
return this.zipFun(...result);
}
}
export class FromAsyncIterator {
constructor(source, close) {
this.source = source;
if (source.return && close) {
this.return = () => Promise.all([source.return?.(), close?.()]);
}
else if (source.return) {
this.return = () => source.return?.();
}
else if (close) {
this.return = close;
}
}
next() {
return this.source.next();
}
async fastNext(otherwise) {
const result = await this.source.next();
if (result.done) {
await closeIters(this);
return AsyncOptLazy.toMaybePromise(otherwise);
}
return result.value;
}
}
export class FromIterator extends AsyncFastIteratorBase {
constructor(iterator, close) {
super();
this.iterator = iterator;
if (close !== undefined) {
this.return = close;
}
}
async fastNext(otherwise) {
const result = this.iterator.next();
if (result.done) {
await closeIters(this);
return AsyncOptLazy.toMaybePromise(otherwise);
}
return result.value;
}
}
export class FromPromise extends AsyncFastIteratorBase {
constructor(promise, asyncStreamSourceHelpers, close) {
super();
this.promise = promise;
this.asyncStreamSourceHelpers = asyncStreamSourceHelpers;
this.return = async () => {
if (close) {
await close();
}
if (this.iterator) {
await this.iterator.return?.();
}
};
}
async fastNext(otherwise) {
if (this.iterator === undefined) {
const source = await this.promise();
this.iterator = this.asyncStreamSourceHelpers
.fromAsyncStreamSource(source)[Symbol.asyncIterator]();
}
return this.iterator.fastNext(otherwise);
}
}
export class AsyncPrependIterator extends AsyncFastIteratorBase {
constructor(source, item) {
super();
this.source = source;
this.item = item;
this.prependDone = false;
this.return = async () => {
if (this.prependDone)
return closeIters(this.source);
};
}
fastNext(otherwise) {
if (this.prependDone) {
return this.source.fastNext(otherwise);
}
this.prependDone = true;
return AsyncOptLazy.toMaybePromise(this.item);
}
}
export class AsyncAppendIterator extends AsyncFastIteratorBase {
constructor(source, item) {
super();
this.source = source;
this.item = item;
this.appendDone = false;
this.return = async () => {
if (!this.appendDone)
return closeIters(source);
};
}
async fastNext(otherwise) {
if (this.appendDone)
return AsyncOptLazy.toMaybePromise(otherwise);
const done = Symbol('Done');
const value = await this.source.fastNext(done);
if (done !== value)
return value;
this.appendDone = true;
return AsyncOptLazy.toMaybePromise(this.item);
}
}
export class AsyncIndexedIterator extends AsyncFastIteratorBase {
constructor(source, startIndex = 0) {
super();
this.source = source;
this.startIndex = startIndex;
this.index = startIndex;
this.return = () => closeIters(source);
}
async fastNext(otherwise) {
const done = Symbol('Done');
const value = await this.source.fastNext(done);
if (done === value) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
return [this.index++, value];
}
}
export class AsyncMapIterator extends AsyncFastIteratorBase {
constructor(source, mapFun) {
super();
this.source = source;
this.mapFun = mapFun;
this.state = TraverseState();
this.return = () => closeIters(source);
}
async fastNext(otherwise) {
const state = this.state;
const done = Symbol('Done');
const next = await this.source.fastNext(done);
if (done === next) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
return this.mapFun(next, state.nextIndex());
}
}
export class AsyncMapPureIterator extends AsyncFastIteratorBase {
constructor(source, mapFun, args) {
super();
this.source = source;
this.mapFun = mapFun;
this.args = args;
this.return = () => closeIters(source);
}
async fastNext(otherwise) {
const done = Symbol('Done');
const next = await this.source.fastNext(done);
if (done === next)
return AsyncOptLazy.toMaybePromise(otherwise);
return this.mapFun(next, ...this.args);
}
}
export class AsyncConcatIterator extends AsyncFastIteratorBase {
constructor(source, otherSources, asyncStreamSourceHelpers) {
super();
this.source = source;
this.otherSources = otherSources;
this.asyncStreamSourceHelpers = asyncStreamSourceHelpers;
this.sourceIndex = 0;
this.iterator = source[Symbol.asyncIterator]();
this.return = () => closeIters(this.iterator);
}
async fastNext(otherwise) {
const done = Symbol('Done');
let value;
const length = this.otherSources.length;
const { asyncStreamSourceHelpers } = this;
while (done === (value = await this.iterator.fastNext(done))) {
if (this.sourceIndex >= length) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
let nextSource = this.otherSources[this.sourceIndex++];
while (asyncStreamSourceHelpers.isEmptyAsyncStreamSourceInstance(nextSource)) {
if (this.sourceIndex >= length) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
nextSource = this.otherSources[this.sourceIndex++];
}
this.iterator = asyncStreamSourceHelpers
.fromAsyncStreamSource(nextSource)[Symbol.asyncIterator]();
}
return value;
}
}
export class AsyncFilterIterator extends AsyncFastIteratorBase {
constructor(source, pred, negate) {
super();
this.source = source;
this.pred = pred;
this.negate = negate;
this.state = TraverseState();
this.return = () => closeIters(source);
}
async fastNext(otherwise) {
const state = this.state;
if (state.halted) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
const done = Symbol('Done');
let value;
const source = this.source;
const pred = this.pred;
const halt = state.halt;
const negate = this.negate;
while (!state.halted && done !== (value = await source.fastNext(done))) {
const cond = await pred(value, state.nextIndex(), halt);
if (cond !== negate)
return value;
}
if (state.halted && done !== value) {
await closeIters(this);
}
return AsyncOptLazy.toMaybePromise(otherwise);
}
}
export class AsyncFilterPureIterator extends AsyncFastIteratorBase {
constructor(source, pred, args, negate) {
super();
this.source = source;
this.pred = pred;
this.args = args;
this.negate = negate;
this.return = () => closeIters(source);
}
async fastNext(otherwise) {
const done = Symbol('Done');
let value;
const source = this.source;
const pred = this.pred;
const args = this.args;
const negate = this.negate;
while (done !== (value = await source.fastNext(done))) {
const cond = await pred(value, ...args);
if (cond !== negate)
return value;
}
return AsyncOptLazy.toMaybePromise(otherwise);
}
}
export class AsyncCollectIterator extends AsyncFastIteratorBase {
constructor(source, collectFun) {
super();
this.source = source;
this.collectFun = collectFun;
this.state = TraverseState();
this.return = () => closeIters(source);
}
async fastNext(otherwise) {
const state = this.state;
if (state.halted) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
const { halt } = state;
const done = Symbol('Done');
let value;
const source = this.source;
const collectFun = this.collectFun;
try {
while (!state.halted && done !== (value = await source.fastNext(done))) {
const result = await collectFun(value, state.nextIndex(), CollectFun.Skip, halt);
if (CollectFun.Skip === result)
continue;
return result;
}
return AsyncOptLazy.toMaybePromise(otherwise);
}
finally {
if (state.halted && done !== value) {
await closeIters(this);
}
}
}
}
export class AsyncDropWhileIterator extends AsyncFastIteratorBase {
constructor(source, pred, negate) {
super();
this.source = source;
this.pred = pred;
this.negate = negate;
this.pass = false;
this.index = 0;
this.return = () => closeIters(source);
}
async fastNext(otherwise) {
const source = this.source;
if (this.pass)
return source.fastNext(otherwise);
const done = Symbol('Done');
let value;
const negate = this.negate;
while (done !== (value = await source.fastNext(done))) {
this.pass = (await this.pred(value, this.index++)) === negate;
if (this.pass)
return value;
}
return AsyncOptLazy.toMaybePromise(otherwise);
}
}
export class AsyncTakeIterator extends AsyncFastIteratorBase {
constructor(source, amount) {
super();
this.source = source;
this.amount = amount;
this.i = 0;
this.return = () => closeIters(source);
}
async fastNext(otherwise) {
if (this.i++ >= this.amount) {
await closeIters(this);
this.return = undefined;
return AsyncOptLazy.toMaybePromise(otherwise);
}
return this.source.fastNext(otherwise);
}
}
export class AsyncDropIterator extends AsyncFastIteratorBase {
constructor(source, amount) {
super();
this.source = source;
this.amount = amount;
this.return = () => closeIters(source);
this.remain = amount;
}
async fastNext(otherwise) {
const source = this.source;
if (this.remain <= 0)
return source.fastNext(otherwise);
const done = Symbol('Done');
let value;
while (done !== (value = await source.fastNext(done))) {
if (this.remain-- <= 0) {
return value;
}
}
return AsyncOptLazy.toMaybePromise(otherwise);
}
}
export class AsyncRepeatIterator extends AsyncFastIteratorBase {
constructor(source, amount) {
super();
this.source = source;
this.amount = amount;
this.isEmpty = true;
this.iterator = source[Symbol.asyncIterator]();
this.return = () => closeIters(this.iterator);
this.remain = amount;
}
async fastNext(otherwise) {
const done = Symbol('Done');
const iterator = this.iterator;
let value = await iterator.fastNext(done);
if (done !== value) {
this.isEmpty = false;
return value;
}
if (this.isEmpty) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
if (undefined !== this.remain) {
this.remain--;
if (this.remain <= 0) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
}
this.iterator = this.source[Symbol.asyncIterator]();
value = await this.iterator.fastNext(done);
if (done === value) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
return value;
}
}
export class AsyncReduceIterator extends AsyncFastIteratorBase {
constructor(sourceIterator, reducer) {
super();
this.sourceIterator = sourceIterator;
this.reducer = reducer;
_AsyncReduceIterator_instance.set(this, void 0);
this.return = async () => {
if (undefined !== __classPrivateFieldGet(this, _AsyncReduceIterator_instance, "f") && !__classPrivateFieldGet(this, _AsyncReduceIterator_instance, "f").halted) {
await Promise.all([
closeIters(sourceIterator),
__classPrivateFieldGet(this, _AsyncReduceIterator_instance, "f").onClose(),
]);
}
else {
await closeIters(sourceIterator);
}
};
}
async fastNext(otherwise) {
if (undefined === __classPrivateFieldGet(this, _AsyncReduceIterator_instance, "f")) {
__classPrivateFieldSet(this, _AsyncReduceIterator_instance, await this.reducer.compile(), "f");
}
const reducerInstance = __classPrivateFieldGet(this, _AsyncReduceIterator_instance, "f");
try {
if (reducerInstance.halted) {
return (await AsyncOptLazy.toMaybePromise(otherwise));
}
const done = Symbol('Done');
const nextInput = await this.sourceIterator.fastNext(done);
if (done === nextInput) {
__classPrivateFieldGet(this, _AsyncReduceIterator_instance, "f").halt();
return AsyncOptLazy.toMaybePromise(otherwise);
}
await reducerInstance.next(nextInput);
return reducerInstance.getOutput();
}
finally {
if (reducerInstance.halted) {
this.return?.();
this.return = undefined;
}
}
}
}
_AsyncReduceIterator_instance = new WeakMap();
export class AsyncTransformerFastIterator extends AsyncFastIteratorBase {
constructor(sourceIterator, transformer) {
super();
this.sourceIterator = sourceIterator;
this.transformer = transformer;
_AsyncTransformerFastIterator_done.set(this, false);
_AsyncTransformerFastIterator_instance.set(this, void 0);
_AsyncTransformerFastIterator_currentValues.set(this, void 0);
this.return = async () => {
if (undefined !== __classPrivateFieldGet(this, _AsyncTransformerFastIterator_instance, "f")) {
await Promise.all([
closeIters(sourceIterator),
__classPrivateFieldGet(this, _AsyncTransformerFastIterator_instance, "f").onClose(),
]);
}
else {
await closeIters(sourceIterator);
}
};
}
async fastNext(otherwise) {
if (__classPrivateFieldGet(this, _AsyncTransformerFastIterator_done, "f")) {
return AsyncOptLazy.toPromise(otherwise);
}
if (undefined === __classPrivateFieldGet(this, _AsyncTransformerFastIterator_instance, "f")) {
__classPrivateFieldSet(this, _AsyncTransformerFastIterator_instance, await AsyncTransformer.from(this.transformer).compile(), "f");
}
const transformerInstance = __classPrivateFieldGet(this, _AsyncTransformerFastIterator_instance, "f");
const done = Symbol('done');
let nextValue;
while (undefined === __classPrivateFieldGet(this, _AsyncTransformerFastIterator_currentValues, "f") ||
done === (nextValue = await __classPrivateFieldGet(this, _AsyncTransformerFastIterator_currentValues, "f").fastNext(done))) {
const nextSource = await this.sourceIterator.fastNext(done);
if (done === nextSource) {
if (transformerInstance.halted) {
return AsyncOptLazy.toMaybePromise(otherwise);
}
__classPrivateFieldSet(this, _AsyncTransformerFastIterator_done, true, "f");
transformerInstance.halt();
this.return = undefined;
}
else {
await transformerInstance.next(nextSource);
}
const nextValuesSource = await transformerInstance.getOutput();
__classPrivateFieldSet(this, _AsyncTransformerFastIterator_currentValues, fromAsyncStreamSource(nextValuesSource)[Symbol.asyncIterator](), "f");
}
return nextValue;
}
}
_AsyncTransformerFastIterator_done = new WeakMap(), _AsyncTransformerFastIterator_instance = new WeakMap(), _AsyncTransformerFastIterator_currentValues = new WeakMap();
//# sourceMappingURL=async-fast-iterator-base.mjs.map