@rimbu/stream
Version:
Efficient structure representing a sequence of elements, with powerful operations for TypeScript
1,028 lines • 68.6 kB
JavaScript
"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