UNPKG

@rimbu/stream

Version:

Efficient structure representing a sequence of elements, with powerful operations for TypeScript

1,028 lines 68.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AsyncReducer = void 0; var tslib_1 = require("tslib"); var base_1 = require("@rimbu/base"); var common_1 = require("@rimbu/common"); var stream_1 = require("@rimbu/stream"); var async_stream_custom_cjs_1 = require("../async-custom/async-stream-custom.cjs"); function identity(value) { return value; } /** * Combines multiple (asynchronous) reducers in an array of the same input type into a single reducer that * forwards each incoming value to all reducers, and when output is requested will return an array containing * the corresponding output of each reducer. */ function combineArr() { var _this = this; var reducers = []; for (var _i = 0; _i < arguments.length; _i++) { reducers[_i] = arguments[_i]; } return AsyncReducer.create(function (initHalt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var allHalted, result; var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: allHalted = true; return [4 /*yield*/, Promise.all(reducers.map(function (reducer) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var instance; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, AsyncReducer.from(reducer).compile()]; case 1: instance = _a.sent(); allHalted = allHalted && instance.halted; return [2 /*return*/, instance]; } }); }); }))]; case 1: result = _a.sent(); if (allHalted) { initHalt(); } return [2 /*return*/, result]; } }); }); }, function (state, elem, index, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var allHalted; var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: allHalted = true; return [4 /*yield*/, Promise.all(stream_1.Stream.from(state).mapPure(function (reducer) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (reducer.halted) return [2 /*return*/]; return [4 /*yield*/, reducer.next(elem)]; case 1: _a.sent(); allHalted = allHalted && reducer.halted; return [2 /*return*/]; } }); }); }))]; case 1: _a.sent(); if (allHalted) { halt(); } return [2 /*return*/, state]; } }); }); }, function (state) { return Promise.all(stream_1.Stream.from(state).mapPure(function (reducerInstance) { return reducerInstance.getOutput(); })); }, function (state, err) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, Promise.all(stream_1.Stream.from(state).mapPure(function (reducer) { return reducer.onClose(err); }))]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }); } /** * Combines multiple (asynchronous) reducers in an object's values of the same input type into a single reducer that * forwards each incoming value to all reducers, and when output is requested will return an object containing * the corresponding output of each reducer at the matching object property. */ function combineObj(reducerObj) { var _this = this; return AsyncReducer.create(function (initHalt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var result, allHalted; var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: result = {}; allHalted = true; return [4 /*yield*/, Promise.all(stream_1.Stream.fromObject(reducerObj).mapPure(function (_a) { return tslib_1.__awaiter(_this, [_a], void 0, function (_b) { var instance; var _c = tslib_1.__read(_b, 2), key = _c[0], reducer = _c[1]; return tslib_1.__generator(this, function (_d) { switch (_d.label) { case 0: return [4 /*yield*/, AsyncReducer.from(reducer).compile()]; case 1: instance = _d.sent(); result[key] = instance; allHalted = allHalted && instance.halted; return [2 /*return*/]; } }); }); }))]; case 1: _a.sent(); if (allHalted) { initHalt(); } return [2 /*return*/, result]; } }); }); }, function (state, elem, index, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var allHalted; var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: allHalted = true; return [4 /*yield*/, Promise.all(stream_1.Stream.fromObjectValues(state).mapPure(function (reducerInstance) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!!reducerInstance.halted) return [3 /*break*/, 2]; return [4 /*yield*/, reducerInstance.next(elem)]; case 1: _a.sent(); allHalted = allHalted && reducerInstance.halted; _a.label = 2; case 2: return [2 /*return*/]; } }); }); }))]; case 1: _a.sent(); if (allHalted) { halt(); } return [2 /*return*/, state]; } }); }); }, function (state) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var result; var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: result = {}; return [4 /*yield*/, Promise.all(stream_1.Stream.fromObject(state).mapPure(function (_a) { return tslib_1.__awaiter(_this, [_a], void 0, function (_b) { var _c, _d; var _e = tslib_1.__read(_b, 2), key = _e[0], reducerInstance = _e[1]; return tslib_1.__generator(this, function (_f) { switch (_f.label) { case 0: _c = result; _d = key; return [4 /*yield*/, reducerInstance.getOutput()]; case 1: _c[_d] = _f.sent(); return [2 /*return*/]; } }); }); }))]; case 1: _a.sent(); return [2 /*return*/, result]; } }); }); }, function (state, err) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, Promise.all(stream_1.Stream.fromObjectValues(state).mapPure(function (reducerInstance) { return reducerInstance.onClose(err); }))]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }); } var AsyncReducer; (function (AsyncReducer) { var _this = this; /** * A base class that can be used to easily create `AsyncReducer` instances. * @typeparam I - the input value type * @typeparam O - the output value type * @typeparam S - the internal state type */ var Base = /** @class */ (function () { function Base(init, next, stateToResult, onClose) { this.init = init; this.next = next; this.stateToResult = stateToResult; this.onClose = onClose; } Base.prototype.filterInput = function (pred, options) { var _this = this; if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a; return create(function () { return _this.compile(); }, function (state, elem, index, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, pred(elem, index, halt)]; case 1: if (!((_a.sent()) !== negate)) return [3 /*break*/, 3]; return [4 /*yield*/, state.next(elem)]; case 2: _a.sent(); if (state.halted) { halt(); } _a.label = 3; case 3: return [2 /*return*/, state]; } }); }); }, function (state) { return state.getOutput(); }, function (state, err) { return state.onClose(err); }); }; Base.prototype.mapInput = function (mapFun) { var _this = this; return create(this.init, function (state, elem, index, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var _a, _b; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: _a = this.next; _b = [state]; return [4 /*yield*/, mapFun(elem, index)]; case 1: return [2 /*return*/, _a.apply(this, _b.concat([_c.sent(), index, halt]))]; } }); }); }, this.stateToResult, this.onClose); }; Base.prototype.flatMapInput = function (flatMapFun) { var _this = this; return create(function () { return _this.compile(); }, function (state, elem, index, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var elems, iter, done, value, _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: if (state.halted) { halt(); return [2 /*return*/, state]; } return [4 /*yield*/, flatMapFun(elem, index)]; case 1: elems = _b.sent(); iter = (0, async_stream_custom_cjs_1.fromAsyncStreamSource)(elems)[Symbol.asyncIterator](); done = Symbol(); _b.label = 2; case 2: _a = done; return [4 /*yield*/, iter.fastNext(done)]; case 3: if (!(_a !== (value = _b.sent()))) return [3 /*break*/, 5]; return [4 /*yield*/, state.next(value)]; case 4: _b.sent(); if (state.halted) { halt(); return [3 /*break*/, 5]; } return [3 /*break*/, 2]; case 5: return [2 /*return*/, state]; } }); }); }, function (state) { return state.getOutput(); }, function (state, err) { return state.onClose(err); }); }; Base.prototype.collectInput = function (collectFun) { var _this = this; return create(function () { return _this.compile(); }, function (state, elem, index, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var nextElem; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, collectFun(elem, index, common_1.CollectFun.Skip, halt)]; case 1: nextElem = _a.sent(); if (!(common_1.CollectFun.Skip !== nextElem)) return [3 /*break*/, 3]; return [4 /*yield*/, state.next(nextElem)]; case 2: _a.sent(); if (state.halted) { halt(); } _a.label = 3; case 3: return [2 /*return*/, state]; } }); }); }, function (state) { return state.getOutput(); }, function (state, err) { return state.onClose(err); }); }; Base.prototype.mapOutput = function (mapFun) { var _this = this; return create(this.init, this.next, function (state, index, halted) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: _a = mapFun; return [4 /*yield*/, this.stateToResult(state, index, halted)]; case 1: return [2 /*return*/, _a.apply(void 0, [_b.sent(), index, halted])]; } }); }); }, this.onClose); }; Base.prototype.takeOutput = function (amount) { var _this = this; if (amount <= 0) { return create(function (initHalt) { initHalt(); return _this.init(initHalt); }, this.next, this.stateToResult, this.onClose); } return create(this.init, function (state, next, index, halt) { if (index >= amount - 1) { halt(); } return _this.next(state, next, index, halt); }, this.stateToResult, this.onClose); }; Base.prototype.takeOutputUntil = function (pred, options) { var _this = this; if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a; return create(this.init, function (state, next, index, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var nextState, nextOutput; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.next(state, next, index, halt)]; case 1: nextState = _a.sent(); return [4 /*yield*/, this.stateToResult(nextState, index, false)]; case 2: nextOutput = _a.sent(); return [4 /*yield*/, pred(nextOutput, index)]; case 3: if ((_a.sent()) !== negate) { halt(); } return [2 /*return*/, nextState]; } }); }); }, this.stateToResult, this.onClose); }; Base.prototype.takeInput = function (amount) { if (amount <= 0) { return create(this.init, identity, this.stateToResult, this.onClose); } return this.filterInput(function (_, i, halt) { if (i >= amount - 1) { halt(); } return i < amount; }); }; Base.prototype.dropInput = function (amount) { if (amount <= 0) { return this; } return this.filterInput(function (_, i) { return i >= amount; }); }; Base.prototype.sliceInput = function (from, amount) { if (from === void 0) { from = 0; } if (undefined === amount) return this.dropInput(from); if (amount <= 0) return create(this.init, identity, this.stateToResult); if (from <= 0) return this.takeInput(amount); return this.takeInput(amount).dropInput(from); }; Base.prototype.chain = function (nextReducers) { var _this = this; return AsyncReducer.create(function (initHalt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var iterator, activeInstance, output, creator, nextReducer; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: iterator = (0, async_stream_custom_cjs_1.fromAsyncStreamSource)(nextReducers)[Symbol.asyncIterator](); return [4 /*yield*/, this.compile()]; case 1: activeInstance = (_a.sent()); if (!(undefined !== activeInstance && activeInstance.halted)) return [3 /*break*/, 9]; return [4 /*yield*/, activeInstance.getOutput()]; case 2: output = _a.sent(); _a.label = 3; case 3: return [4 /*yield*/, iterator.fastNext()]; case 4: creator = _a.sent(); if (undefined === creator) { initHalt(); return [2 /*return*/, { activeInstance: activeInstance, iterator: iterator, }]; } return [4 /*yield*/, common_1.AsyncOptLazy.toMaybePromise(creator, output)]; case 5: nextReducer = _a.sent(); return [4 /*yield*/, AsyncReducer.from(nextReducer).compile()]; case 6: activeInstance = _a.sent(); return [4 /*yield*/, activeInstance.getOutput()]; case 7: output = _a.sent(); _a.label = 8; case 8: if (activeInstance.halted) return [3 /*break*/, 3]; _a.label = 9; case 9: return [2 /*return*/, { activeInstance: activeInstance, iterator: iterator, }]; } }); }); }, function (state, next, index, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var output, creator, nextReducer, _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, state.activeInstance.next(next)]; case 1: _b.sent(); _b.label = 2; case 2: if (!state.activeInstance.halted) return [3 /*break*/, 7]; return [4 /*yield*/, state.activeInstance.getOutput()]; case 3: output = _b.sent(); return [4 /*yield*/, state.iterator.fastNext()]; case 4: creator = _b.sent(); if (undefined === creator) { halt(); return [2 /*return*/, state]; } return [4 /*yield*/, common_1.AsyncOptLazy.toMaybePromise(creator, output)]; case 5: nextReducer = _b.sent(); _a = state; return [4 /*yield*/, AsyncReducer.from(nextReducer).compile()]; case 6: _a.activeInstance = _b.sent(); return [3 /*break*/, 2]; case 7: return [2 /*return*/, state]; } }); }); }, function (state) { return state.activeInstance.getOutput(); }); }; Base.prototype.compile = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var instance; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: instance = new AsyncReducer.InstanceImpl(this); return [4 /*yield*/, instance.initialize()]; case 1: _a.sent(); return [2 /*return*/, instance]; } }); }); }; return Base; }()); AsyncReducer.Base = Base; /** * The default `AsyncReducer.Impl` implementation. * @typeparam I - the input element type * @typeparam O - the output element type * @typeparam S - the reducer state type */ var InstanceImpl = /** @class */ (function () { function InstanceImpl(reducer) { var _this = this; this.reducer = reducer; this.___index = 0; this.___initialized = false; this.___halted = false; this.___closed = false; this.halt = function () { if (_this.___closed) { throw new AsyncReducer.ReducerClosedError(); } _this.___halted = true; }; this.next = function (value) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: if (!this.___initialized) { throw new AsyncReducer.ReducerNotInitializedError(); } if (this.___closed) { throw new AsyncReducer.ReducerClosedError(); } if (this.___halted) { throw new AsyncReducer.ReducerHaltedError(); } _a = this; return [4 /*yield*/, this.reducer.next(this.___state, value, this.___index++, this.halt)]; case 1: _a.___state = _b.sent(); return [2 /*return*/]; } }); }); }; } InstanceImpl.prototype.initialize = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: if (this.___closed) { throw new AsyncReducer.ReducerClosedError(); } _a = this; return [4 /*yield*/, this.reducer.init(this.halt)]; case 1: _a.___state = _b.sent(); this.___initialized = true; return [2 /*return*/]; } }); }); }; Object.defineProperty(InstanceImpl.prototype, "halted", { get: function () { return this.___halted; }, enumerable: false, configurable: true }); Object.defineProperty(InstanceImpl.prototype, "index", { get: function () { return this.___index; }, enumerable: false, configurable: true }); InstanceImpl.prototype.getOutput = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { if (!this.___initialized) { throw new AsyncReducer.ReducerNotInitializedError(); } return [2 /*return*/, this.reducer.stateToResult(this.___state, this.index, this.halted)]; }); }); }; InstanceImpl.prototype.onClose = function (err) { return tslib_1.__awaiter(this, void 0, void 0, function () { var _a, _b; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: if (this.___closed) { throw new AsyncReducer.ReducerClosedError(); } this.___closed = true; return [4 /*yield*/, ((_b = (_a = this.reducer).onClose) === null || _b === void 0 ? void 0 : _b.call(_a, this.___state, err))]; case 1: _c.sent(); return [2 /*return*/]; } }); }); }; return InstanceImpl; }()); AsyncReducer.InstanceImpl = InstanceImpl; /** * Returns an `AsyncReducer` with the given options: * @param init - the optionally lazy and/or promised initial state value * @param next - returns (potentially asynchronously) the next state value based on the given inputs:<br/> * - current: the current state<br/> * - next: the current input value<br/> * - index: the input index value<br/> * - halt: function that, when called, ensures no more elements are passed to the reducer * @param stateToResult - a potentially asynchronous function that converts the current state to an output value * @param onClose - (optional) a function that will be called when the reducer will no longer receive values * @typeparam I - the input value type * @typeparam O - the output value type * @typeparam S - the internal state type */ function create(init, next, stateToResult, onClose) { return new AsyncReducer.Base(init, next, stateToResult, onClose); } AsyncReducer.create = create; /** * Returns an `AsyncReducer` of which the input, state, and output types are the same. * @param init - the optionally lazy and/or promised initial state value * @param next - returns (potentially asynchronously) the next state value based on the given inputs:<br/> * - current: the current state<br/> * - next: the current input value<br/> * - index: the input index value<br/> * - halt: function that, when called, ensures no more elements are passed to the reducer * @param stateToResult - a potentially asynchronous function that converts the current state to an output value * @param onClose - (optional) a function that will be called when the reducer will no longer receive values * @typeparam T - the overall value type */ function createMono(init, next, stateToResult, onClose) { return create(init, next, stateToResult !== null && stateToResult !== void 0 ? stateToResult : identity, onClose); } AsyncReducer.createMono = createMono; /** * Returns an `AsyncReducer` of which the state and output types are the same. * @param init - the optionally lazy and/or promised initial state value * @param next - returns (potentially asynchronously) the next state value based on the given inputs:<br/> * - current: the current state<br/> * - next: the current input value<br/> * - index: the input index value<br/> * - halt: function that, when called, ensures no more elements are passed to the reducer * @param stateToResult - a potentially asynchronous function that converts the current state to an output value * @param onClose - (optional) a function that will be called when the reducer will no longer receive values * @typeparam I - the input value type * @typeparam O - the output value type */ function createOutput(init, next, stateToResult, onClose) { return create(init, next, stateToResult !== null && stateToResult !== void 0 ? stateToResult : identity, onClose); } AsyncReducer.createOutput = createOutput; /** * Returns an `AsyncReducer` that uses the given `init` and `next` values to fold the input values into * result values. * @param init - an (optionally lazy) initial result value * @param next - a (potentially async) function taking the following arguments:<br/> * - current - the current result value<br/> * - value - the next input value<br/> * - index: the input index value<br/> * - halt: function that, when called, ensures no more elements are passed to the reducer * @typeparam T - the input type * @typeparam R - the output type */ function fold(init, next) { return AsyncReducer.createOutput(function () { return common_1.AsyncOptLazy.toMaybePromise(init); }, next); } AsyncReducer.fold = fold; /** * Returns an `AsyncReducer` from a given `Reducer` or `AsyncReducer` instance. * @param reducer - the input reducer to convert * @typeparam I - the input element type * @typeparam O - the output element type */ function from(reducer) { if (reducer instanceof AsyncReducer.Base) { return reducer; } return AsyncReducer.create(reducer.init, reducer.next, reducer.stateToResult); } AsyncReducer.from = from; /** * Returns a `Reducer` that remembers the minimum value of the inputs using the given `compFun` to compare input values * @param compFun - a comparison function for two input values, returning 0 when equal, positive when greater, negetive when smaller * @param otherwise - (default: undefineds) a fallback value when there were no input values given * @typeparam T - the element type * @typeparam O - the fallback value type * @example * ```ts * const stream = Stream.of('abc', 'a', 'abcde', 'ab') * console.log(stream.minBy((s1, s2) => s1.length - s2.length)) * // 'a' * ``` */ AsyncReducer.minBy = function (compFun, otherwise) { var token = Symbol(); return create(function () { return token; }, function (state, next) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (token === state) return [2 /*return*/, next]; return [4 /*yield*/, compFun(state, next)]; case 1: return [2 /*return*/, (_a.sent()) < 0 ? state : next]; } }); }); }, function (state) { return token === state ? common_1.AsyncOptLazy.toMaybePromise(otherwise) : state; }); }; /** * Returns a `Reducer` that remembers the minimum value of the numberic inputs. * @param otherwise - (default: undefined) a fallback value when there were no input values given * @typeparam O - the fallback value type * @example * ```ts * console.log(Stream.of(5, 3, 7, 4).reduce(Reducer.min())) * // => 3 * ``` */ // prettier-ignore AsyncReducer.min = function (otherwise) { return create(function () { return undefined; }, function (state, next) { return undefined !== state && state < next ? state : next; }, function (state) { return state !== null && state !== void 0 ? state : common_1.AsyncOptLazy.toMaybePromise(otherwise); }); }; /** * Returns a `Reducer` that remembers the maximum value of the inputs using the given `compFun` to compare input values * @param compFun - a comparison function for two input values, returning 0 when equal, positive when greater, negetive when smaller * @param otherwise - (default: undefined) a fallback value when there were no input values given * @typeparam T - the element type * @typeparam O - the fallback value type * @example * ```ts * const stream = Stream.of('abc', 'a', 'abcde', 'ab') * console.log(stream.maxBy((s1, s2) => s1.length - s2.length)) * // 'abcde' * ``` */ AsyncReducer.maxBy = function (compFun, otherwise) { var token = Symbol(); return create(function () { return token; }, function (state, next) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (token === state) return [2 /*return*/, next]; return [4 /*yield*/, compFun(state, next)]; case 1: return [2 /*return*/, (_a.sent()) > 0 ? state : next]; } }); }); }, function (state) { return token === state ? common_1.AsyncOptLazy.toMaybePromise(otherwise) : state; }); }; /** * Returns a `Reducer` that remembers the maximum value of the numberic inputs. * @param otherwise - (default: undefined) a fallback value when there were no input values given * @typeparam O - the fallback value type * @example * ```ts * console.log(Stream.of(5, 3, 7, 4).reduce(Reducer.max())) * // => 7 * ``` */ // prettier-ignore AsyncReducer.max = function (otherwise) { return create(function () { return undefined; }, function (state, next) { return undefined !== state && state > next ? state : next; }, function (state) { return state !== null && state !== void 0 ? state : common_1.AsyncOptLazy.toMaybePromise(otherwise); }); }; /** * Returns an `AsyncReducer` that remembers the first input value. * @param otherwise - (default: undefined) a fallback value to output if no input value has been provided * @typeparam T - the input value type * @typeparam O - the fallback value type * @example * ```ts * await AsyncStream.from(Stream.range{ amount: 10 })).reduce(AsyncReducer.first()) * // => 0 * ``` */ AsyncReducer.first = function (otherwise) { return create(function () { return undefined; }, function (state, next, _, halt) { halt(); return next; }, function (state, index) { return index <= 0 ? common_1.AsyncOptLazy.toMaybePromise(otherwise) : state; }); }; /** * Returns an `AsyncReducer` that remembers the last input value. * @param otherwise - (default: undefined) a fallback value to output if no input value has been provided * @typeparam T - the input value type * @typeparam O - the fallback value type * @example * ```ts * await AsyncStream.from(Stream.range{ amount: 10 })).reduce(AsyncReducer.last()) * // => 9 * ``` */ AsyncReducer.last = function (otherwise) { return create(function () { return undefined; }, function (_, next) { return next; }, function (state, index) { return index <= 0 ? common_1.AsyncOptLazy.toMaybePromise(otherwise) : state; }); }; /** * Returns an AsyncReducer that only produces an output value when having receives exactly one * input value, otherwise will return the `otherwise` value or undefined. * @param otherwise - the fallback value to return when more or less than one value is received. * @typeparam T - the element type * @typeparam O - the fallback value type */ AsyncReducer.single = function (otherwise) { return create(function () { return undefined; }, function (state, next, index, halt) { if (index > 1) { halt(); } return next; }, function (state, index) { return index !== 1 ? common_1.AsyncOptLazy.toMaybePromise(otherwise) : state; }); }; /** * Returns an `AsyncReducer` that ouputs false as long as no input value satisfies given `pred`, true otherwise. * @typeparam T - the element type * @param pred - a potentiall async function taking an input value and its index, and returning true if the value satisfies the predicate * @param options - (optional) an object containing the following properties:<br/> * - negate: (default: false) when true will invert the given predicate */ function some(pred, options) { if (options === void 0) { options = {}; } return AsyncReducer.nonEmpty.filterInput(pred, options); } AsyncReducer.some = some; /** * Returns an `AsyncReducer` that ouputs true as long as all input values satisfy the given `pred`, false otherwise. * @typeparam T - the element type * @param pred - a potentially async function taking an input value and its index, and returning true if the value satisfies the predicate * @param options - (optional) an object containing the following properties:<br/> * - negate: (default: false) when true will invert the given predicate */ function every(pred, options) { if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a; return AsyncReducer.isEmpty.filterInput(pred, { negate: !negate }); } AsyncReducer.every = every; /** * Returns an `AsyncReducer` that ouputs true when the received elements match the given `other` async stream source according to the `eq` instance, false otherwise. * @typeparam T - the element type * @param other - an async stream source containg elements to match against * @param options - (optional) an object containing the following properties:<br/> * - eq: (default: Eq.objectIs) the `Eq` instance to use to compare elements * - negate: (default: false) when true will invert the given predicate */ function equals(other, options) { var _this = this; if (options === void 0) { options = {}; } var _a = options.eq, eq = _a === void 0 ? common_1.Eq.objectIs : _a, _b = options.negate, negate = _b === void 0 ? false : _b; var sliceStream = (0, async_stream_custom_cjs_1.fromAsyncStreamSource)(other); var done = Symbol(); return AsyncReducer.create(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { var iter, nextSeq; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: iter = sliceStream[Symbol.asyncIterator](); return [4 /*yield*/, iter.fastNext(done)]; case 1: nextSeq = _a.sent(); return [2 /*return*/, { iter: iter, nextSeq: nextSeq, result: false }]; } }); }); }, function (state, next, _, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: if (done === state.nextSeq) { halt(); state.result = false; return [2 /*return*/, state]; } if (eq(next, state.nextSeq) === negate) { halt(); state.result = false; return [2 /*return*/, state]; } _a = state; return [4 /*yield*/, state.iter.fastNext(done)]; case 1: _a.nextSeq = _b.sent(); if (done === state.nextSeq) { state.result = true; } return [2 /*return*/, state]; } }); }); }, function (state, index, halted) { return !halted && done === state.nextSeq; }); } AsyncReducer.equals = equals; /** * An `AsyncReducer` that outputs true if no input values are received, false otherwise. * @example * ```ts * await AsyncStream.of(1, 2, 3).reduce(AsyncReducer.isEmpty)) * // => false * ``` */ AsyncReducer.isEmpty = createOutput(function () { return true; }, function (_, __, ___, halt) { halt(); return false; }); /** * An `AsyncReducer` that outputs true if one or more input values are received, false otherwise. * @example * ```ts * await AsyncStream.of(1, 2, 3).reduce(AsyncReducer.nonEmpty)) * // => true * ``` */ AsyncReducer.nonEmpty = createOutput(function () { return false; }, function (_, __, ___, halt) { halt(); return true; }); /** * Returns a `AsyncReducer` that returns true if the first input values match the given `slice` values repeated `amount` times. Otherwise, * returns false. * @param slice - a async sequence of elements to match against * @param options - (optional) an object containing the following properties:<br/> * - amount: (detaulf: 1) the amount of elements to find * - eq: (default: Eq.objectIs) the `Eq` instance to use to compare elements */ function startsWithSlice(slice, options) { var _this = this; if (options === void 0) { options = {}; } var sliceStream = (0, async_stream_custom_cjs_1.fromAsyncStreamSource)(slice); var done = Symbol(); var _a = options.eq, eq = _a === void 0 ? common_1.Eq.objectIs : _a, _b = options.amount, amount = _b === void 0 ? 1 : _b; return AsyncReducer.create(function (initHalt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var sliceIter, sliceValue; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: sliceIter = sliceStream[Symbol.asyncIterator](); return [4 /*yield*/, sliceIter.fastNext(done)]; case 1: sliceValue = _a.sent(); if (done === sliceValue || amount <= 0) { initHalt(); return [2 /*return*/, { sliceIter: sliceIter, sliceValue: sliceValue, remain: 0 }]; } return [2 /*return*/, { sliceIter: sliceIter, sliceValue: sliceValue, remain: amount, }]; } }); }); }, function (state, next, _, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var _a, _b; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: if (done === state.sliceValue) { base_1.RimbuError.throwInvalidStateError(); } if (!eq(next, state.sliceValue)) return [3 /*break*/, 5]; _a = state; return [4 /*yield*/, state.sliceIter.fastNext(done)]; case 1: _a.sliceValue = _c.sent(); if (!(done === state.sliceValue)) return [3 /*break*/, 4]; state.remain--; if (!(state.remain <= 0)) return [3 /*break*/, 2]; halt(); return [3 /*break*/, 4]; case 2: state.sliceIter = sliceStream[Symbol.asyncIterator](); _b = state; return [4 /*yield*/, state.sliceIter.fastNext(done)]; case 3: _b.sliceValue = _c.sent(); _c.label = 4; case 4: return [3 /*break*/, 6]; case 5: halt(); _c.label = 6; case 6: return [2 /*return*/, state]; } }); }); }, function (state) { return state.remain <= 0; }); } AsyncReducer.startsWithSlice = startsWithSlice; /** * Returns an `AsyncReducer` that returns true if the last input values match the given `slice` values repeated `amount` times. Otherwise, * returns false. * @param slice - a async sequence of elements to match against * @param options - (optional) an object containing the following properties:<br/> * - amount: (detaulf: 1) the amount of elements to find * - eq: (default: Eq.objectIs) the `Eq` instance to use to compare elements */ function endsWithSlice(slice, options) { var _this = this; if (options === void 0) { options = {}; } var sliceStream = async_stream_custom_cjs_1.AsyncStreamConstructorsImpl.from(slice); var done = Symbol(); var newReducerSpec = AsyncReducer.startsWithSlice(slice, options); return AsyncReducer.create(function (initHalt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var sliceIter, sliceValue, _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: sliceIter = sliceStream[Symbol.asyncIterator](); return [4 /*yield*/, sliceIter.fastNext(done)]; case 1: sliceValue = _b.sent(); if (done === sliceValue) { initHalt(); } _a = Set.bind; return [4 /*yield*/, newReducerSpec.compile()]; case 2: return [2 /*return*/, new (_a.apply(Set, [void 0, [_b.sent()]]))()]; } }); }); }, function (state, nextValue) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var state_1, state_1_1, instance, e_1_1, newReducerInstance; var e_1, _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 6, 7, 8]); state_1 = tslib_1.__values(state), state_1_1 = state_1.next(); _b.label = 1; case 1: if (!!state_1_1.done) return [3 /*break*/, 5]; instance