iter-tools-es
Version:
The iterable toolbox
163 lines (128 loc) • 3.04 kB
JavaScript
const {
iterableCurry,
callReturn
} = require('../../internal/iterable.js');
const {
IterableIterator
} = require('../../internal/iterable-iterator.js');
const {
parallelEach
} = require('../../internal/parallel-each.js');
const {
Peekerator
} = require('../../internal/peekerator.js');
const {
__map
} = require('../$map/map.js');
const {
__toArray
} = require('../$to-array/to-array.js');
const _ = Symbol.for('_');
const __advance = Symbol.for('__advance');
class SummarizedPeekerator extends Peekerator {
constructor(iterator, first, inputSummary) {
super(iterator, first);
this[_].inputSummary = inputSummary;
}
advance() {
this[_].inputSummary.advanceBuffer(this);
}
[__advance]() {
super.advance();
}
}
class InputSummaryInternal {
constructor() {
this.buffers = [];
this.notDoneBuffer = null;
this.index = 0;
}
init(buffers) {
this.buffers = buffers;
this.updateNotDone();
}
updateNotDone() {
this.notDoneBuffer = this.buffers.find(buffer => !buffer.done);
}
advanceBuffer(buffer) {
const wasDone = buffer.done;
buffer[__advance]();
this.index++;
if (!wasDone && buffer.done) {
this.updateNotDone();
}
}
}
class InputSummary {
constructor(internal) {
this[_] = internal;
}
advance() {
throw new Error('advance() is not supported on an interleave summary');
}
get current() {
return {
value: this.value,
done: this.done
};
}
get value() {
return this[_].notDoneBuffer;
}
get done() {
return this[_].notDoneBuffer === undefined;
}
get index() {
return this[_].index;
}
}
exports.InputSummary = InputSummary;
class Interleaver extends IterableIterator {
constructor(sources, strategy, options) {
super();
this.sources = sources;
this.strategy = strategy;
this.options = options;
this.initialized = false;
this.inputSummary = new InputSummaryInternal(sources);
}
init() {
this.initialized = true;
const {
strategy,
options,
inputSummary
} = this;
this.buffers = __toArray(__map(this.sources, source => SummarizedPeekerator.from(source, inputSummary)));
this.iterator = strategy(options, new InputSummary(inputSummary), ...this.buffers);
inputSummary.init(this.buffers);
}
returnBuffers() {
parallelEach(this.buffers, buffer => buffer.return());
}
next() {
if (!this.initialized) this.init();
const step = this.iterator.next();
if (step.done) this.returnBuffers();
return step;
}
return() {
callReturn(this.iterator);
this.returnBuffers();
return {
value: undefined,
done: true
};
}
}
function __interleave(sources, strategy, options = {}) {
return new Interleaver(sources, strategy, options);
}
exports.__interleave = __interleave;
const interleave = /*#__PURE__*/iterableCurry(__interleave, {
variadic: true,
growRight: true,
minArgs: 1,
maxArgs: 2
});
exports.interleave = interleave;