// src/index.ts var DoneIteratorResult = Object.freeze({ value: void 0, done: true }); function hasMethods(methods, obj) { return methods.every((method) => typeof obj[method] === "function"); } function isIterable(value) { return typeof value[Symbol.iterator] === "function"; } function isIterator(value) { return typeof value.next === "function"; } function isBuffer(value) { return ArrayBuffer.isView(value); } function isArrayLike(value) { return Array.isArray(value) || value instanceof Array; } var IteratorEnumerator = class _IteratorEnumerator { _iterator; _consumed = false; _current; get current() { return this._current; } constructor(iterator) { this._iterator = iterator; } static from(iterator) { return new _IteratorEnumerator(iterator); } moveNext() { if (!this._consumed) { const { value, done } = this._iterator.next(); this._current = value; if (done) { this._consumed = true; } return !done; } else { return false; } } reset() { } toIterator() { return this; } next(...[_value]) { const done = this.moveNext(); return { value: this.current, done }; } return(value) { return this._iterator.return?.(value) ?? DoneIteratorResult; } throw(e) { return this._iterator.throw?.(e) ?? DoneIteratorResult; } }; var CachedIteratorEnumerator = class _CachedIteratorEnumerator { _iterator; _cache = []; _index = -1; get current() { return this._cache[this._index]; } constructor(iterator) { this._iterator = new IteratorEnumerator(iterator); } static from(iterator) { return new _CachedIteratorEnumerator(iterator); } moveNext() { this._index += 1; if (this._cache.length > this._index) { return true; } else if (this._iterator.moveNext()) { this._cache.push(this._iterator.current); return true; } else { return false; } } reset() { this._index = -1; } toIterator() { return this; } next(...[_value]) { const done = this.moveNext(); return { value: this.current, done }; } return(value) { return this._iterator.return(value); } throw(e) { return this._iterator.throw(e); } }; var IterableEnumerator = class { _iterable; _factory; _enumerator; get current() { return this._enumerator?.current; } constructor(iterable, factory = IteratorEnumerator.from) { this._iterable = iterable; this._factory = factory; this._enumerator = this._createEnumerator(); } static fromIterable(iterable, factory) { return new this(iterable, factory); } moveNext() { return this._enumerator?.moveNext() ?? false; } _createIterator() { return this._iterable[Symbol.iterator](); } _createEnumerator() { return this._factory(this._createIterator()); } reset() { this._enumerator = this._createEnumerator(); } toIterator() { return this._createIterator(); } next(...[_value]) { const done = !this.moveNext(); return { value: this.current, done }; } return(value) { if (isIterator(this._enumerator)) { return this._enumerator?.return?.(value) || DoneIteratorResult; } else { return DoneIteratorResult; } } throw(e) { if (isIterator(this._enumerator)) { return this._enumerator?.throw?.(e) || DoneIteratorResult; } else { return DoneIteratorResult; } } }; function toArrayLikeBuffer(buffer) { return Object.defineProperty(buffer, "length", { get: function() { return buffer.byteLength; } }); } var ArrayEnumerator = class _ArrayEnumerator { _array; _index = -1; get current() { return this._array[this._index]; } constructor(array) { this._array = array; } static from(array) { if (ArrayBuffer.isView(array)) { return new _ArrayEnumerator(toArrayLikeBuffer(array)); } else { return new _ArrayEnumerator(array); } } [Symbol.iterator]() { return this._array[Symbol.iterator](); } setIndex(index) { this._index = index; } moveNext() { this._index += 1; return this._index < this._array.length; } reset() { this._index = -1; } toIterator() { return this._array[Symbol.iterator](); } next(...[_value]) { const done = this.moveNext(); return { value: this.current, done }; } return(_value) { return DoneIteratorResult; } throw(_e) { return DoneIteratorResult; } }; var Enumerator = class _Enumerator { _enumerator; _index = 0; get current() { return this._enumerator.current; } constructor(enumerator) { this._enumerator = enumerator; } static fromIterable(iterable) { if (isArrayLike(iterable) || ArrayBuffer.isView(iterable)) { return ArrayEnumerator.from(iterable); } else { return new this(new IterableEnumerator(iterable)); } } static fromIterator(iterator, cache = true) { if (cache) { return new CachedIteratorEnumerator(iterator); } else { return new IteratorEnumerator(iterator); } } static toIterator(enumerator) { return new this(enumerator); } [Symbol.iterator]() { return this.toIterator(); } toIterator() { return _Enumerator.toIterator(this); } moveNext() { this._index += 1; return this._enumerator.moveNext(); } reset() { this._enumerator.reset(); } next(...[_value]) { const done = this.moveNext(); return { value: this.current, done }; } return(_value) { return DoneIteratorResult; } throw(_e) { return DoneIteratorResult; } }; var HelperEnumerator = class _HelperEnumerator { _enumerator; _index = 0; get current() { return this._enumerator.current; } constructor(enumerator) { this._enumerator = enumerator; } static toIterator(enumerator) { return new this(enumerator); } [Symbol.iterator]() { return this.toIterator(); } toIterator() { return _HelperEnumerator.toIterator(this); } moveNext() { this._index += 1; return this._enumerator.moveNext(); } reset() { this._enumerator.reset(); } next(...[_value]) { const done = this.moveNext(); return { value: this.current, done }; } return(_value) { return DoneIteratorResult; } throw(_e) { return DoneIteratorResult; } }; var DropEnumerator = class extends HelperEnumerator { _limit; constructor(enumerator, limit) { super(enumerator); this._limit = limit; } moveNext() { let next = super.moveNext(); while (this._limit > 0 && next) { next = super.moveNext(); this._limit -= 1; } return next; } }; var FilterEnumerator = class extends HelperEnumerator { _filter; constructor(enumerator, filter) { super(enumerator); this._filter = filter; } moveNext() { let next = super.moveNext(); while (next && !this._filter(this.current, this._index)) { next = super.moveNext(); } return next; } }; var FlatMapEnumerator = class { _enumerator; _flatMap; _inner; _index = -1; constructor(enumerator, flatMap) { this._enumerator = enumerator; this._flatMap = flatMap; } get current() { return this._inner?.current; } moveNext() { if (this._inner && this._inner.moveNext()) { return true; } const next = this._enumerator.moveNext(); if (!next) { return false; } this._index += 1; this._inner = this._flatMap(this._enumerator.current, this._index); return this._inner.moveNext(); } reset() { this._index = -1; this._inner = void 0; this._enumerator.reset(); } toIterator() { return HelperEnumerator.toIterator(this); } }; var MapEnumerator = class { _enumerator; _map; _current; _index = -1; get current() { return this._current; } constructor(enumerator, map) { this._enumerator = enumerator; this._map = map; } toIterator() { return HelperEnumerator.toIterator(this); } moveNext() { this._index += 1; const next = this._enumerator.moveNext(); if (next) { this._current = this._map(this._enumerator.current, this._index); } return next; } reset() { this._index = -1; this._enumerator.reset(); } }; var TakeEnumerator = class extends HelperEnumerator { _limit; constructor(enumerator, limit) { super(enumerator); this._limit = limit; } moveNext() { if (this._limit < 0) { return false; } else { super.moveNext(); this._limit -= 1; return true; } } }; var FusedEnumerator = class { _enumerators; _index = 0; get current() { return this._cur()?.current; } constructor(enumerators) { this._enumerators = enumerators; } _cur() { return this._enumerators[this._index]; } _done() { return this._index >= this._enumerators.length; } toIterator() { return HelperEnumerator.toIterator(this); } moveNext() { while (!this._done() && !this._cur().moveNext()) { this._index += 1; } return this._done(); } reset() { const len = this._enumerators.length; for (let i = 0; i < len; i++) { this._enumerators[i].reset(); } this._index = 0; } }; var Enumerable = class _Enumerable { _enumerator; constructor(enumerator) { this._enumerator = enumerator; } static from(value) { if (this.isEnumerable(value)) { return value; } else if (this.isEnumerator(value)) { return new _Enumerable(value); } else if (isIterable(value)) { const enumerator = Enumerator.fromIterable(value); if (isArrayLike(value)) { return new ArrayEnumerble(enumerator); } else { return new _Enumerable(enumerator); } } else if (isIterator(value)) { return new _Enumerable( Enumerator.fromIterator(value) ); } else { throw new TypeError("value is not enumerable"); } } static isEnumerable(value) { return typeof value["enumerator"] === "function"; } static isEnumerator(value) { return hasMethods(["moveNext", "reset", "toIterator"], value); } [Symbol.iterator]() { return this._enumerator.toIterator(); } at(index) { while (index >= 0 && this._enumerator.moveNext()) { index -= 1; } const value = this._enumerator.current; this._enumerator.reset(); return value; } atOrDefault(index, defaultValue) { const value = this.at(index); return value || defaultValue; } atOrElse(index, defaultValue) { const value = this.at(index); return value || defaultValue(); } concat(other) { return new _Enumerable( new FusedEnumerator([this._enumerator, other.enumerator()]) ); } drop(limit) { return new _Enumerable(new DropEnumerator(this._enumerator, limit)); } enumerator() { return this._enumerator; } //entries(): IEnumerator { //} every(predicate) { let index = 0; while (this._enumerator.moveNext()) { if (!predicate(this._enumerator.current, index)) { return false; } index += 1; } this._enumerator.reset(); return true; } filter(predicate) { return new _Enumerable(new FilterEnumerator(this._enumerator, predicate)); } flatMap(fn) { return new _Enumerable(new FlatMapEnumerator(this._enumerator, fn)); } map(fn) { return new _Enumerable(new MapEnumerator(this._enumerator, fn)); } some(predicate) { let index = 0; while (this._enumerator.moveNext()) { if (predicate(this._enumerator.current, index)) { return true; } index += 1; } this._enumerator.reset(); return false; } take(limit) { return new _Enumerable(new TakeEnumerator(this._enumerator, limit)); } }; var ArrayEnumerble = class extends Enumerable { at(index) { if (this._enumerator instanceof ArrayEnumerator) { this._enumerator.setIndex(index); return this._enumerator.current; } else { return super.at(index); } } }; export { ArrayEnumerator, ArrayEnumerble, CachedIteratorEnumerator, DropEnumerator, Enumerable, Enumerator, FilterEnumerator, FlatMapEnumerator, FusedEnumerator, HelperEnumerator, IterableEnumerator, IteratorEnumerator, MapEnumerator, TakeEnumerator, isArrayLike, isBuffer, isIterable, isIterator };