asclasit
Version:
ASync CLasses + ASync ITerators
118 lines (91 loc) • 2.54 kB
JavaScript
const AsIt = require('./object');
AsIt.chain_(async function* voidIter() { }, 'void');
function bound() { return this; }
AsIt.chain_(async function* shim(iter) {
if (!iter[Symbol.asyncIterator] && !iter[Symbol.iterator]) {
iter = Object.create(iter);
iter[Symbol.asyncIterator] = bound;
}
for await (const item of iter) yield item;
});
AsIt.chain_(async function* from(arg, strOk) {
const iter = AsIt.getIter(arg, strOk);
if (iter) yield* iter;
else if (typeof arg === 'object') yield* AsIt.objectEntries.gen(arg);
else yield arg;
});
AsIt.chain_(async function* concat(...args) {
for await (const arg of args) {
yield* AsIt.from.gen.call(this, arg);
}
});
AsIt.chain_(AsIt.concat.gen, 'append');
AsIt.chain_(async function* prepend(...args) {
for (let i = args.length - 1; i >= 0; i--) {
yield* AsIt.from.gen.call(this, args[i]);
}
});
AsIt.make_(async function* repeat(from, times, strOk, ...args) {
while (times--) yield* AsIt.getIter(from, strOk, ...args);
});
class ForkBufferLimitExceededError extends Error { message = 'fork buffer limit exceeded'; }
Object.assign(AsIt, {ForkBufferLimitExceededError});
async function* _fork(iter, limit, i) {
const o = iter.forkObj;
const {b, u} = o;
try {
while (true) {
const d = i - o.i;
if (d >= b.length) {
if (o.wait) {
await o.wait;
continue;
}
o.wait = iter.next();
const {value, done} = await o.wait;
o.wait = null;
if (done) return;
if (o.n > 0) {
u.push(o.n);
if (b.push(value) === limit) throw new ForkBufferLimitExceededError();
i++;
}
yield value;
} else {
if (--u[d] <= 0) {
o.i++;
u.shift();
yield b.shift();
} else {
yield b[d];
}
i++;
}
}
} finally {
const l = b.length;
if (l) {
for (let d = i - o.i; d < l; d++) u[d]--;
//if (!u[l - 1]) { o.i += l; b.splice(0); u.splice(0); }
}
if (!(o.n--)) iter.forkObj = null;
}
}
AsIt.value_(function fork(iter, limit) {
if (iter.forkSrc) iter = iter.forkSrc;
let o = iter.forkObj;
if (o) {
o.n++;
} else {
iter.forkObj = o = {b: [], u: [], i: 0, n: 0};
}
const forked = _fork.call(this, iter, limit, o.i);
forked.forkSrc = iter;
if (this instanceof AsIt) {
const wrapped = new this.constructor(forked);
return wrapped;
} else {
return forked;
}
});
module.exports = AsIt;