iterable-joiner
Version:
combine multiple Iterable or AsyncIterable objects into one
162 lines (161 loc) • 7.69 kB
JavaScript
"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);
}