iteragain
Version:
Javascript Iterable/Iterator/Generator-function utilities.
72 lines • 2.37 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SeekableIterator = void 0;
/**
* Wraps `iterator` to allow for seeking backwards and forwards. An internal cache of length `maxLength` is kept and
* progressively added to when iterating forwards.
*/
class SeekableIterator {
constructor(iterator, maxLength = Infinity) {
this.iterator = iterator;
this.maxLength = maxLength;
this.cache = [];
this.i = 0;
this.iteratorDone = false;
}
get elements() {
return this.cache;
}
get done() {
// If the iterator is done, then determine if `i` is at the end of the cache.
return this.iteratorDone ? !this.cache.length || this.i >= this.cache.length : false;
}
[Symbol.iterator]() {
return this;
}
next(...args) {
if (this.done)
return { done: true, value: undefined };
const cachedValue = this.cache[this.i++];
if (cachedValue !== undefined)
return { done: false, value: cachedValue };
const next = this.iterator.next(...args);
if (next.done)
this.iteratorDone = true;
else
this.add(next.value);
return next;
}
/**
* Seeks forward/backwards to the index `i`. `i` may be any positive or negative number. Negative numbers seek
* starting from the end of the internal cache (e.g. -1 is the last element).
*/
seek(i) {
if (i < 0)
i = this.cache.length + i;
if (i > this.i)
while (this.i < i && !this.done)
this.next();
else if (i < this.i)
this.i = i;
}
/**
* Peek ahead of where the current iteration is. This doesn't consume any values of the iterator.
* @param ahead optional, the number of elements to peek ahead.
*/
peek(ahead = 1) {
const result = [];
for (let i = 0; i < ahead; i++)
result.push(this.next().value);
this.i -= ahead;
return result;
}
/** Add `value` to the `cache`. */
add(value) {
this.cache.push(value);
if (this.cache.length > this.maxLength)
this.cache.shift();
}
}
exports.SeekableIterator = SeekableIterator;
exports.default = SeekableIterator;
//# sourceMappingURL=SeekableIterator.js.map