UNPKG

iterable-joiner

Version:

combine multiple Iterable or AsyncIterable objects into one

162 lines (161 loc) 7.69 kB
"use strict"; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Async = void 0; const semasync_1 = require("semasync"); var Async; (function (Async) { var _Abstract_iterables, _Abstract_handlers; class Abstract { constructor(...iterables) { _Abstract_iterables.set(this, void 0); _Abstract_handlers.set(this, { add: [], remove: [], }); __classPrivateFieldSet(this, _Abstract_iterables, iterables, "f"); } get iterables() { return __classPrivateFieldGet(this, _Abstract_iterables, "f"); } async *[(_Abstract_iterables = new WeakMap(), _Abstract_handlers = new WeakMap(), Symbol.asyncIterator)]() { const self = this; const state = { iterableStates: [], mergeMutex: new semasync_1.Mutex(), running: true, }; state.mergeMutex.acquire(); __classPrivateFieldGet(this, _Abstract_iterables, "f").forEach(startIterating); __classPrivateFieldGet(this, _Abstract_handlers, "f").add.push(startIterating); __classPrivateFieldGet(this, _Abstract_handlers, "f").remove.push(stopIterating); yield* this._merge(state); __classPrivateFieldGet(this, _Abstract_handlers, "f").add.splice(__classPrivateFieldGet(this, _Abstract_handlers, "f").add.indexOf(startIterating), 1); __classPrivateFieldGet(this, _Abstract_handlers, "f").remove.splice(__classPrivateFieldGet(this, _Abstract_handlers, "f").remove.indexOf(startIterating), 1); function startIterating(iterable) { const idx = self.iterables.indexOf(iterable); if (idx === -1) { return false; } const status = { item: undefined, iterable, mutex: new semasync_1.Mutex(), ready: false, running: true }; state.iterableStates.splice(idx, 0, status); state.running = true; status.mutex.acquire(); (async () => { for await (const item of iterable) { status.item = item; status.ready = true; if (state.mergeMutex.waiting) { state.mergeMutex.release(); } await status.mutex.acquire(); if (status.running === false) { break; } } if (status.running === true) { stopIterating(iterable); } })(); return true; } function stopIterating(iterable) { const idx = state.iterableStates.findIndex((status) => status.iterable === iterable); if (idx >= 0) { const [status] = state.iterableStates.splice(idx, 1); status.running = false; status.mutex.release(); state.running = (state.iterableStates.some((status) => status.running)); if (state.running && state.mergeMutex.waiting) { state.mergeMutex.release(); } return true; } return false; } } addIterable(it, idx = __classPrivateFieldGet(this, _Abstract_iterables, "f").length) { if (isAsyncIterable(it) === false || __classPrivateFieldGet(this, _Abstract_iterables, "f").includes(it) === true) { return false; } if (typeof idx !== "number") { return false; } else { if (idx < 0) { idx = 0; } else if (idx > __classPrivateFieldGet(this, _Abstract_iterables, "f").length) { idx = __classPrivateFieldGet(this, _Abstract_iterables, "f").length; } } __classPrivateFieldGet(this, _Abstract_iterables, "f").splice(idx, 0, it); __classPrivateFieldGet(this, _Abstract_handlers, "f").add.forEach(f => f(it)); return true; } removeIterable(it) { if (isAsyncIterable(it) === false || __classPrivateFieldGet(this, _Abstract_iterables, "f").includes(it) === false) { return false; } __classPrivateFieldGet(this, _Abstract_iterables, "f").splice(__classPrivateFieldGet(this, _Abstract_iterables, "f").indexOf(it), 1); __classPrivateFieldGet(this, _Abstract_handlers, "f").remove.forEach(f => f(it)); return true; } } Async.Abstract = Abstract; class Equitable extends Abstract { constructor() { super(...arguments); this.priority = false; } static join(...iterables) { return new Equitable(...iterables); } _merge(state) { const priority = this.priority; return { async *[Symbol.asyncIterator]() { while (state.iterableStates.length) { if (state.iterableStates.every((status) => status.ready === false)) { await state.mergeMutex.acquire(); } for (const status of state.iterableStates) { if (status.ready) { const item = status.item; status.item = undefined; status.ready = false; if (status.mutex.waiting) { status.mutex.release(); } yield item; if (priority) { break; } } } } } }; } } Async.Equitable = Equitable; class Priority extends Equitable { constructor() { super(...arguments); this.priority = true; } static join(...iterables) { return new Priority(...iterables); } } Async.Priority = Priority; })(Async = exports.Async || (exports.Async = {})); function isAsyncIterable(value) { return value.hasOwnProperty(Symbol.asyncIterator); }