import { assert } from "./asserts.js";
export function* joinIterables(...iters) {
    for (const iter of iters) {
        yield* iter;
    }
}
function* filterIter(iter, p) {
    let index = 0;
    for (const t of iter) {
        if (p(t, index++)) {
            yield t;
        }
    }
}
function* mapIter(iter, f) {
    let index = 0;
    for (const t of iter) {
        yield f(t, index++);
    }
}
export function first(stream) {
    const it = stream[Symbol.iterator]();
    const { value } = it.next();
    it.return?.();
    return value;
}
export function* once(stream) {
    const it = stream[Symbol.iterator]();
    const { value } = it.next();
    if (value !== undefined) {
        yield value;
    }
    it.return?.();
}
// TODO(arv): Use ES2024 Iterable.from when available
// https://github.com/tc39/proposal-iterator-helpers
class IterWrapper {
    iter;
    constructor(iter) {
        this.iter = iter;
    }
    [Symbol.iterator]() {
        return this.iter[Symbol.iterator]();
    }
    map(f) {
        return new IterWrapper(mapIter(this.iter, f));
    }
    filter(p) {
        return new IterWrapper(filterIter(this.iter, p));
    }
}
export function wrapIterable(iter) {
    return new IterWrapper(iter);
}
export function* mergeIterables(iterables, comparator, distinct = false) {
    const iterators = iterables.map(i => i[Symbol.iterator]());
    try {
        const current = iterators.map(i => i.next());
        let lastYielded;
        while (current.some(c => !c.done)) {
            const min = current.reduce((acc, c, i) => {
                if (c.done) {
                    return acc;
                }
                if (acc === undefined || comparator(c.value, acc[0]) < 0) {
                    return [c.value, i];
                }
                return acc;
            }, undefined);
            assert(min !== undefined, 'min is undefined');
            current[min[1]] = iterators[min[1]].next();
            if (lastYielded !== undefined &&
                distinct &&
                comparator(lastYielded, min[0]) === 0) {
                continue;
            }
            lastYielded = min[0];
            yield min[0];
        }
    }
    finally {
        for (const it of iterators) {
            it.return?.();
        }
    }
}
//# sourceMappingURL=iterables.js.map