UNPKG

@rimbu/stream

Version:

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

471 lines 24.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AsyncTransformer = void 0; var tslib_1 = require("tslib"); var common_1 = require("@rimbu/common"); var stream_1 = require("@rimbu/stream"); var async_1 = require("@rimbu/stream/async"); var AsyncTransformer; (function (AsyncTransformer) { var _this = this; /** * Returns an AsyncTransformer based on a given synchronous or asynchronous transformer. * @param transformer - the transformer to convert * @typeparam T - the input element type * @typeparam R - the result stream element type */ function from(transformer) { return async_1.AsyncReducer.from(transformer); } AsyncTransformer.from = from; /** * Returns an async transformer that produces windows/collections of `windowSize` size, each * window starting `skipAmount` of elements after the previous, and optionally collected * by a custom reducer. * @typeparam T - the input element type * @typeparam R - the window type * @param windowSize - the amount of elements for each window * @param options - (optional) object specifying the following properties<br/> * - skipAmount: (default: `windowSize`) the amount of elements between the start of each window<br/> * - collector: (default: Reducer.toArray()) the reducer to use to convert elements to windows * @example * ```ts * await AsyncStream.of(1, 2, 3, 4, 5, 6) * .transform(AsyncTransformer.window(3)) * .toArray() * // => [[1, 2, 3], [4, 5, 6]] * ``` */ AsyncTransformer.window = function (windowSize, options) { if (options === void 0) { options = {}; } var _a = options.skipAmount, skipAmount = _a === void 0 ? windowSize : _a, _b = options.collector, collector = _b === void 0 ? stream_1.Reducer.toArray() : _b; return async_1.AsyncReducer.create(function () { return new Set(); }, function (state, elem, index) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var state_1, state_1_1, instance, e_1_1, newInstance; 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 = state_1_1.value; if (!(instance.index >= windowSize || instance.halted)) return [3 /*break*/, 2]; state.delete(instance); return [3 /*break*/, 4]; case 2: return [4 /*yield*/, instance.next(elem)]; case 3: _b.sent(); _b.label = 4; case 4: state_1_1 = state_1.next(); return [3 /*break*/, 1]; case 5: return [3 /*break*/, 8]; case 6: e_1_1 = _b.sent(); e_1 = { error: e_1_1 }; return [3 /*break*/, 8]; case 7: try { if (state_1_1 && !state_1_1.done && (_a = state_1.return)) _a.call(state_1); } finally { if (e_1) throw e_1.error; } return [7 /*endfinally*/]; case 8: if (!(index % skipAmount === 0)) return [3 /*break*/, 11]; return [4 /*yield*/, async_1.AsyncReducer.from(collector).compile()]; case 9: newInstance = _b.sent(); return [4 /*yield*/, newInstance.next(elem)]; case 10: _b.sent(); state.add(newInstance); _b.label = 11; case 11: return [2 /*return*/, state]; } }); }); }, function (state, _, halted) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { if (halted) { return [2 /*return*/, async_1.AsyncStream.empty()]; } return [2 /*return*/, async_1.AsyncStream.from(state).collect(function (instance, _, skip) { return instance.index === windowSize ? instance.getOutput() : skip; })]; }); }); }); }; /** * Returns an async transformer that applies the given flatMap function to each element of the input stream, * and concatenates all the resulting resulting streams into one stream. * @typeparam T - the input element type * @typeparam T2 - the output element type * @param flatMapFun - a potentially async function that maps each input element to an `AsyncStreamSource`. * The function receives three parameters:<br/> * - `value`: the current element being processed<br/> * - `index`: the index of the current element in the input stream<br/> * - `halt`: a function that can be called to halt further processing of the input stream<br/> */ function flatMap(flatMapFun) { return async_1.AsyncReducer.createOutput(function () { return async_1.AsyncStream.empty(); }, function (state, next, index, halt) { return flatMapFun(next, index, halt); }, function (state, _, halted) { return (halted ? async_1.AsyncStream.empty() : state); }); } AsyncTransformer.flatMap = flatMap; /** * Returns an async transformer that applies the given flatMap function to each element of the input stream, * and concatenates all the resulting resulting streams into one stream, where each resulting element is tupled * with the originating input element. * @typeparam T - the input element type * @typeparam T2 - the output element type * @param flatMapFun - a potentially async function that maps each input element to an `AsyncStreamSource`. * The function receives three parameters:<br/> * - `value`: the current element being processed<br/> * - `index`: the index of the current element in the input stream<br/> * - `halt`: a function that can be called to halt further processing of the input stream<br/> */ function flatZip(flatMapFun) { var _this = this; return flatMap(function (value, 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: _b = (_a = async_1.AsyncStream).from; return [4 /*yield*/, flatMapFun(value, index, halt)]; case 1: return [2 /*return*/, _b.apply(_a, [_c.sent()]).mapPure(function (stream) { return [value, stream]; })]; } }); }); }); } AsyncTransformer.flatZip = flatZip; /** * Returns an async transformer that filters elements from the input stream based on the provided predicate function. * @typeparam T - the type of elements in the input stream * @param pred - a potentially async predicate function that determines whether an element should be included in the output stream, receiving:<br/> * - `value`: the current element being processed<br/> * - `index`: the index of the current element in the input stream<br/> * - `halt`: a function that can be called to halt further processing of the input stream * @param options - (optional) object specifying the following properties:<br/> * - negate: (default: false) if true, the predicate will be negated * @note if the predicate is a type guard, the return type is automatically inferred */ AsyncTransformer.filter = function (pred, options) { if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a; return flatMap(function (value, 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(value, index, halt)]; case 1: return [2 /*return*/, (_a.sent()) !== negate ? async_1.AsyncStream.of(value) : async_1.AsyncStream.empty()]; } }); }); }); }; /** * Returns an `AsyncTransformer` instance that converts or filters its input values using given `collectFun` before passing them to the reducer. * @param collectFun - a potentially async function receiving the following arguments, and returns a new value or `skip` if the value should be skipped:<br/> * - `value`: the next value<br/> * - `index`: the value index<br/> * - `skip`: a token that, when returned, will not add a value to the resulting collection<br/> * - `halt`: a function that, when called, ensures no next elements are passed * @typeparam T - the input element type * @typeparam R - the result element type */ function collect(collectFun) { var _this = this; return flatMap(function (value, index, halt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var result; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, collectFun(value, index, common_1.CollectFun.Skip, halt)]; case 1: result = _a.sent(); return [2 /*return*/, common_1.CollectFun.Skip === result ? async_1.AsyncStream.empty() : async_1.AsyncStream.of(result)]; } }); }); }); } AsyncTransformer.collect = collect; /** * Returns an `AsyncTransformer` that inserts the given `sep` stream source elements between each received input element. * @param sep - the async StreamSource to insert between each received element * @typeparam T - the input and output element type */ function intersperse(sep) { return flatMap(function (value, index) { return index === 0 ? async_1.AsyncStream.of(value) : async_1.AsyncStream.from(sep).append(value); }); } AsyncTransformer.intersperse = intersperse; /** * Returns an `AsyncTransformer` that outputs the index of each received element that satisfies the given predicate. * @param pred - a potentially async predicate function taking an element * @param options - (optional) object specifying the following properties<br/> * - negate: (default: false) when true will negate the given predicate * @typeparam T - the input element type */ function indicesWhere(pred, options) { if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a; return flatMap(function (value, index) { return pred(value) !== negate ? async_1.AsyncStream.of(index) : async_1.AsyncStream.empty(); }); } AsyncTransformer.indicesWhere = indicesWhere; /** * Returns an `AsyncTransformer` that applies the given `pred` function to each received element, and collects the received elements * into a `collector` that will be returned as output every time the predicate returns true. * @typeparam T - the input element type * @typeparam R - the collector result type * @param pred - a potentially async predicate function taking an element * @param options - (optional) object specifying the following properties<br/> * - negate: (default: false) when true will negate the given predicate<br/> * - collector: (default: Reducer.toArray()) an AsyncReducer that can accept multiple values and reduce them into a single value of type `R`. */ function splitWhere(pred, options) { var _this = this; if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a, _b = options.collector, collector = _b === void 0 ? stream_1.Reducer.toArray() : _b; return async_1.AsyncReducer.create(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: _a = {}; return [4 /*yield*/, async_1.AsyncReducer.from(collector).compile()]; case 1: return [2 /*return*/, (_a.collection = _b.sent(), _a.done = false, _a)]; } }); }); }, function (state, nextValue, index) { 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 (!state.done) return [3 /*break*/, 2]; state.done = false; _a = state; return [4 /*yield*/, async_1.AsyncReducer.from(collector).compile()]; case 1: _a.collection = _b.sent(); _b.label = 2; case 2: return [4 /*yield*/, pred(nextValue, index)]; case 3: if (!((_b.sent()) === negate)) return [3 /*break*/, 5]; return [4 /*yield*/, state.collection.next(nextValue)]; case 4: _b.sent(); return [3 /*break*/, 6]; case 5: state.done = true; _b.label = 6; case 6: return [2 /*return*/, state]; } }); }); }, function (state, _, halted) { return state.done !== halted ? async_1.AsyncStream.of(state.collection.getOutput()) : async_1.AsyncStream.empty(); }); } AsyncTransformer.splitWhere = splitWhere; /** * Returns an `AsyncTransformer` that collects the received elements * into a `collector` that will be returned as output every time the input matches the given `sepElem` value. * @typeparam T - the input element type * @typeparam R - the collector result type * @param pred - a potentially async predicate function taking an element * @param options - (optional) object specifying the following properties<br/> * - eq - (default: `Eq.objectIs`) the equality testing function * - negate: (default: false) when true will negate the given predicate<br/> * - collector: (default: Reducer.toArray()) an AsyncReducer that can accept multiple values and reduce them into a single value of type `R`. */ function splitOn(sepElem, 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, _c = options.collector, collector = _c === void 0 ? stream_1.Reducer.toArray() : _c; return async_1.AsyncReducer.create(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: _a = {}; return [4 /*yield*/, async_1.AsyncReducer.from(collector).compile()]; case 1: return [2 /*return*/, (_a.collection = _b.sent(), _a.done = false, _a)]; } }); }); }, function (state, nextValue) { 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 (!state.done) return [3 /*break*/, 2]; state.done = false; _a = state; return [4 /*yield*/, async_1.AsyncReducer.from(collector).compile()]; case 1: _a.collection = _b.sent(); _b.label = 2; case 2: if (!(eq(nextValue, sepElem) === negate)) return [3 /*break*/, 4]; return [4 /*yield*/, state.collection.next(nextValue)]; case 3: _b.sent(); return [3 /*break*/, 5]; case 4: state.done = true; _b.label = 5; case 5: return [2 /*return*/, state]; } }); }); }, function (state, _, halted) { return state.done !== halted ? async_1.AsyncStream.of(state.collection.getOutput()) : async_1.AsyncStream.empty(); }); } AsyncTransformer.splitOn = splitOn; /** * Returns an `AsyncTransformer` that collects the received elements * into a `collector` that will be returned as output every time the input matches the given `sepSlice` sequence of elements. * @typeparam T - the input element type * @typeparam R - the collector result type * @param pred - a potentially async predicate function taking an element * @param options - (optional) object specifying the following properties<br/> * - eq - (default: `Eq.objectIs`) the equality testing function * - collector: (default: Reducer.toArray()) an AsyncReducer that can accept multiple values and reduce them into a single value of type `R`. */ function splitOnSlice(sepSlice, options) { var _this = this; if (options === void 0) { options = {}; } var _a = options.eq, eq = _a === void 0 ? common_1.Eq.objectIs : _a, _b = options.collector, collector = _b === void 0 ? stream_1.Reducer.toArray() : _b; return async_1.AsyncReducer.create(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: _a = { done: false, instances: new Map(), buffer: [] }; return [4 /*yield*/, async_1.AsyncReducer.from(collector).compile()]; case 1: return [2 /*return*/, (_a.result = _b.sent(), _a)]; } }); }); }, function (state, nextValue) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var _a, _b, _c, _d, instance, startIndex, e_2_1, nextStartsWith; var e_2, _e; return tslib_1.__generator(this, function (_f) { switch (_f.label) { case 0: if (!state.done) return [3 /*break*/, 2]; _a = state; return [4 /*yield*/, async_1.AsyncReducer.from(collector).compile()]; case 1: _a.result = _f.sent(); state.done = false; _f.label = 2; case 2: _f.trys.push([2, 9, 10, 11]); _b = tslib_1.__values(state.instances), _c = _b.next(); _f.label = 3; case 3: if (!!_c.done) return [3 /*break*/, 8]; _d = tslib_1.__read(_c.value, 2), instance = _d[0], startIndex = _d[1]; return [4 /*yield*/, instance.next(nextValue)]; case 4: _f.sent(); if (instance.halted) { state.instances.delete(instance); } return [4 /*yield*/, instance.getOutput()]; case 5: if (!_f.sent()) return [3 /*break*/, 7]; state.done = true; return [4 /*yield*/, async_1.AsyncStream.from(stream_1.Stream.fromArray(state.buffer, { range: { end: [startIndex, false] }, })).forEachPure(state.result.next)]; case 6: _f.sent(); state.buffer = []; state.instances.clear(); return [2 /*return*/, state]; case 7: _c = _b.next(); return [3 /*break*/, 3]; case 8: return [3 /*break*/, 11]; case 9: e_2_1 = _f.sent(); e_2 = { error: e_2_1 }; return [3 /*break*/, 11]; case 10: try { if (_c && !_c.done && (_e = _b.return)) _e.call(_b); } finally { if (e_2) throw e_2.error; } return [7 /*endfinally*/]; case 11: return [4 /*yield*/, async_1.AsyncReducer.startsWithSlice(sepSlice, { eq: eq, }).compile()]; case 12: nextStartsWith = _f.sent(); return [4 /*yield*/, nextStartsWith.next(nextValue)]; case 13: _f.sent(); return [4 /*yield*/, nextStartsWith.getOutput()]; case 14: if (!_f.sent()) return [3 /*break*/, 16]; state.done = true; return [4 /*yield*/, async_1.AsyncStream.from(state.buffer).forEachPure(state.result.next)]; case 15: _f.sent(); state.buffer = []; state.instances.clear(); return [2 /*return*/, state]; case 16: if (!nextStartsWith.halted) { state.instances.set(nextStartsWith, state.buffer.length); } _f.label = 17; case 17: if (!(state.instances.size === 0)) return [3 /*break*/, 19]; return [4 /*yield*/, state.result.next(nextValue)]; case 18: _f.sent(); return [3 /*break*/, 20]; case 19: state.buffer.push(nextValue); _f.label = 20; case 20: return [2 /*return*/, state]; } }); }); }, function (state, _, halted) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (state.done === halted) { return [2 /*return*/, async_1.AsyncStream.empty()]; } if (!halted) return [3 /*break*/, 2]; return [4 /*yield*/, async_1.AsyncStream.from(state.buffer).forEachPure(state.result.next)]; case 1: _a.sent(); state.buffer = []; _a.label = 2; case 2: return [2 /*return*/, async_1.AsyncStream.of(state.result.getOutput())]; } }); }); }); } AsyncTransformer.splitOnSlice = splitOnSlice; })(AsyncTransformer || (exports.AsyncTransformer = AsyncTransformer = {})); //# sourceMappingURL=async-transformer.cjs.map