"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runManaged = exports.repeated = exports.orDieWith = exports.orDieWith_ = exports.orDie = exports.orDie_ = exports.never = exports.mapOutEffect = exports.mapOutEffect_ = exports.mapOut = exports.mapOut_ = exports.mergeWith = exports.mergeWith_ = exports.mapEffect = exports.mapEffect_ = exports.mapErrorCause = exports.mapErrorCause_ = exports.mapError = exports.mapError_ = exports.map = exports.map_ = exports.orElse = exports.orElse_ = exports.foldChannel = exports.foldChannel_ = exports.ensuring = exports.ensuring_ = exports.emitCollect = exports.interruptWhenP = exports.interruptWhenP_ = exports.interruptWhen = exports.interruptWhen_ = exports.doneCollect = exports.contramapInEffect = exports.contramapInEffect_ = exports.contramapEffect = exports.contramapEffect_ = exports.contramapIn = exports.contramapIn_ = exports.contramap = exports.contramap_ = exports.concatOut = exports.collect = exports.collect_ = exports.catchAllCause = exports.catchAllCause_ = exports.catchAll = exports.catchAll_ = exports.as = exports.as_ = void 0;
exports.writeChunk = exports.writeAll = exports.toQueue = exports.toHub = exports.fromQueue = exports.fromInput = exports.fromHub = exports.succeed = exports.read = exports.readOrFail = exports.managed = exports.managed_ = exports.interrupt = exports.identity = exports.fromOption = exports.fromEither = exports.concatAll = exports.bufferChunk = exports.buffer = exports.bracketExit = exports.bracketExit_ = exports.bracket = exports.bracket_ = exports.bracketOut = exports.bracketOut_ = exports.zipRight = exports.zipRight_ = exports.zipParRight = exports.zipParRight_ = exports.zipParLeft = exports.zipParLeft_ = exports.zipPar = exports.zipPar_ = exports.zipLeft = exports.zipLeft_ = exports.zip = exports.zip_ = exports.toPull = exports.unit_ = exports.runDrain = exports.runCollect = exports.run = void 0;
// ets_tracing: off
require("../../../Operator");
const Cause = __importStar(require("../../../Cause"));
const AR = __importStar(require("../../../Collections/Immutable/Array"));
const A = __importStar(require("../../../Collections/Immutable/Chunk"));
const Tp = __importStar(require("../../../Collections/Immutable/Tuple"));
const T = __importStar(require("../../../Effect"));
const Effect_1 = require("../../../Effect");
const E = __importStar(require("../../../Either"));
const Ex = __importStar(require("../../../Exit"));
const F = __importStar(require("../../../Fiber"));
const Function_1 = require("../../../Function");
const H = __importStar(require("../../../Hub"));
const M = __importStar(require("../../../Managed"));
const RM = __importStar(require("../../../Managed/ReleaseMap"));
const O = __importStar(require("../../../Option"));
const PR = __importStar(require("../../../Promise"));
const Q = __importStar(require("../../../Queue"));
const Ref = __importStar(require("../../../Ref"));
const executor_1 = require("./_internal/executor");
const MH = __importStar(require("./_internal/mergeHelpers"));
const P = __importStar(require("./_internal/primitives"));
const producer_1 = require("./_internal/producer");
const C = __importStar(require("./core"));
/**
 * Returns a new channel that is the same as this one, except the terminal value of the channel
 * is the specified constant value.
 *
 * This method produces the same result as mapping this channel to the specified constant value.
 */
function as_(self, z2) {
    return map_(self, (_) => z2);
}
exports.as_ = as_;
/**
 * Returns a new channel that is the same as this one, except the terminal value of the channel
 * is the specified constant value.
 *
 * This method produces the same result as mapping this channel to the specified constant value.
 *
 * @ets_data_first as_
 */
function as(z2) {
    return (self) => as_(self, z2);
}
exports.as = as;
/**
 * Returns a new channel that is the same as this one, except if this channel errors for any
 * typed error, then the returned channel will switch over to using the fallback channel returned
 * by the specified error handler.
 */
function catchAll_(self, f) {
    return catchAllCause_(self, (cause) => E.fold_(Cause.failureOrCause(cause), (l) => f(l), (r) => C.failCause(r)));
}
exports.catchAll_ = catchAll_;
/**
 * Returns a new channel that is the same as this one, except if this channel errors for any
 * typed error, then the returned channel will switch over to using the fallback channel returned
 * by the specified error handler.
 *
 * @ets_data_first catchAll_
 */
function catchAll(f) {
    return (self) => catchAll_(self, f);
}
exports.catchAll = catchAll;
/**
 * Returns a new channel that is the same as this one, except if this channel errors for any
 * typed error, then the returned channel will switch over to using the fallback channel returned
 * by the specified error handler.
 */
function catchAllCause_(self, f) {
    return new P.Fold(self, new P.ContinuationK((_) => C.end(_), f));
}
exports.catchAllCause_ = catchAllCause_;
/**
 * Returns a new channel that is the same as this one, except if this channel errors for any
 * typed error, then the returned channel will switch over to using the fallback channel returned
 * by the specified error handler.
 *
 * @ets_data_first catchAllCause_
 */
function catchAllCause(f) {
    return (self) => catchAllCause_(self, f);
}
exports.catchAllCause = catchAllCause;
/**
 * Returns a new channel, which is the same as this one, except its outputs are filtered and
 * transformed by the specified partial function.
 */
function collect_(self, f) {
    const collector = C.readWith((o) => O.fold_(f(o), () => collector, (out2) => zipRight_(C.write(out2), collector)), (e) => C.fail(e), (z) => C.end(z));
    return C.pipeTo_(self, collector);
}
exports.collect_ = collect_;
/**
 * Returns a new channel, which is the same as this one, except its outputs are filtered and
 * transformed by the specified partial function.
 *
 * @ets_data_first collect_
 */
function collect(f) {
    return (self) => collect_(self, f);
}
exports.collect = collect;
/**
 * Returns a new channel, which is the concatenation of all the channels that are written out by
 * this channel. This method may only be called on channels that output other channels.
 */
function concatOut(self) {
    return concatAll(mapOut_(self, (out) => out));
}
exports.concatOut = concatOut;
function contramapReader(f) {
    return C.readWith((_in) => zipRight_(C.write(_in), contramapReader(f)), (err) => C.fail(err), (done) => C.end(f(done)));
}
function contramap_(self, f) {
    return C.pipeTo_(contramapReader(f), self);
}
exports.contramap_ = contramap_;
/**
 * @ets_data_first contramap_
 */
function contramap(f) {
    return (self) => contramap_(self, f);
}
exports.contramap = contramap;
function contramapInReader(f) {
    return C.readWith((_in) => zipRight_(C.write(f(_in)), contramapInReader(f)), (err) => C.fail(err), (done) => C.end(done));
}
function contramapIn_(self, f) {
    return C.pipeTo_(contramapInReader(f), self);
}
exports.contramapIn_ = contramapIn_;
/**
 * @ets_data_first contramapIn_
 */
function contramapIn(f) {
    return (self) => contramapIn_(self, f);
}
exports.contramapIn = contramapIn;
function contramapMReader(f) {
    return C.readWith((_in) => zipRight_(C.write(_in), contramapMReader(f)), (err) => C.fail(err), (done0) => C.fromEffect(f(done0)));
}
function contramapEffect_(self, f) {
    return C.pipeTo_(contramapMReader(f), self);
}
exports.contramapEffect_ = contramapEffect_;
/**
 * @ets_data_first contramapEffect_
 */
function contramapEffect(f) {
    return (self) => contramapEffect_(self, f);
}
exports.contramapEffect = contramapEffect;
function contramapInMReader(f) {
    return C.readWith((_in) => zipRight_(C.chain_(C.fromEffect(f(_in)), (_) => C.write(_)), contramapInMReader(f)), (err) => C.fail(err), (done) => C.end(done));
}
function contramapInEffect_(self, f) {
    return C.pipeTo_(contramapInMReader(f), self);
}
exports.contramapInEffect_ = contramapInEffect_;
/**
 * @ets_data_first contramapInEffect_
 */
function contramapInEffect(f) {
    return (self) => contramapInEffect_(self, f);
}
exports.contramapInEffect = contramapInEffect;
function doneCollectReader(builder) {
    return C.readWith((out) => zipRight_(C.succeedWith(() => {
        builder.append(out);
    }), doneCollectReader(builder)), (err) => C.fail(err), (done) => C.end(done));
}
/**
 * Returns a new channel, which is the same as this one, except that all the outputs are
 * collected and bundled into a tuple together with the terminal value of this channel.
 *
 * As the channel returned from this channel collect's all of this channel's output into an in-
 * memory chunk, it is not safe to call this method on channels that output a large or unbounded
 * number of values.
 */
function doneCollect(self) {
    return C.suspend(() => {
        const builder = A.builder();
        return C.chain_(C.pipeTo_(self, doneCollectReader(builder)), (z) => C.succeedWith(() => Tp.tuple(builder.build(), z)));
    });
}
exports.doneCollect = doneCollect;
/**
 * Returns a new channel, which is the same as this one, except it will be interrupted when the
 * specified effect completes. If the effect completes successfully before the underlying channel
 * is done, then the returned channel will yield the success value of the effect as its terminal
 * value. On the other hand, if the underlying channel finishes first, then the returned channel
 * will yield the success value of the underlying channel as its terminal value.
 */
function interruptWhen_(self, io) {
    return mergeWith_(self, C.fromEffect(io), (selfDone) => MH.done(T.done(selfDone)), (ioDone) => MH.done(T.done(ioDone)));
}
exports.interruptWhen_ = interruptWhen_;
/**
 * Returns a new channel, which is the same as this one, except it will be interrupted when the
 * specified effect completes. If the effect completes successfully before the underlying channel
 * is done, then the returned channel will yield the success value of the effect as its terminal
 * value. On the other hand, if the underlying channel finishes first, then the returned channel
 * will yield the success value of the underlying channel as its terminal value.
 *
 * @ets_data_first interruptWhen_
 */
function interruptWhen(io) {
    return (self) => interruptWhen_(self, io);
}
exports.interruptWhen = interruptWhen;
/**
 * Returns a new channel, which is the same as this one, except it will be interrupted when the
 * specified promise is completed. If the promise is completed before the underlying channel is
 * done, then the returned channel will yield the value of the promise. Otherwise, if the
 * underlying channel finishes first, then the returned channel will yield the value of the
 * underlying channel.
 */
function interruptWhenP_(self, promise) {
    return interruptWhen_(self, PR.await(promise));
}
exports.interruptWhenP_ = interruptWhenP_;
/**
 * Returns a new channel, which is the same as this one, except it will be interrupted when the
 * specified promise is completed. If the promise is completed before the underlying channel is
 * done, then the returned channel will yield the value of the promise. Otherwise, if the
 * underlying channel finishes first, then the returned channel will yield the value of the
 * underlying channel.
 *
 * @ets_data_first interruptWhenP_
 */
function interruptWhenP(promise) {
    return (self) => interruptWhenP_(self, promise);
}
exports.interruptWhenP = interruptWhenP;
/**
 * Returns a new channel that collects the output and terminal value of this channel, which it
 * then writes as output of the returned channel.
 */
function emitCollect(self) {
    return C.chain_(doneCollect(self), (t) => C.write(t));
}
exports.emitCollect = emitCollect;
function ensuring_(self, finalizer) {
    return C.ensuringWith_(self, (_) => finalizer);
}
exports.ensuring_ = ensuring_;
/**
 * @ets_data_first ensuring_
 */
function ensuring(finalizer) {
    return (self) => ensuring_(self, finalizer);
}
exports.ensuring = ensuring;
function foldChannel_(self, onErr, onSucc) {
    return C.foldCauseChannel_(self, (_) => {
        return E.fold_(Cause.failureOrCause(_), (err) => onErr(err), (cause) => C.failCause(cause));
    }, onSucc);
}
exports.foldChannel_ = foldChannel_;
/**
 * @ets_data_first foldChannel_
 */
function foldChannel(onErr, onSucc) {
    return (self) => foldChannel_(self, onErr, onSucc);
}
exports.foldChannel = foldChannel;
/**
 * Returns a new channel that will perform the operations of this one, until failure, and then
 * it will switch over to the operations of the specified fallback channel.
 */
function orElse_(self, that) {
    return catchAll_(self, (_) => that);
}
exports.orElse_ = orElse_;
/**
 * Returns a new channel that will perform the operations of this one, until failure, and then
 * it will switch over to the operations of the specified fallback channel.
 *
 * @ets_data_first orElse_
 */
function orElse(that) {
    return (self) => orElse_(self, that);
}
exports.orElse = orElse;
/**
 * Returns a new channel, which is the same as this one, except the terminal value of the
 * returned channel is created by applying the specified function to the terminal value of this
 * channel.
 */
function map_(self, f) {
    return C.chain_(self, (z) => succeed(f(z)));
}
exports.map_ = map_;
/**
 * Returns a new channel, which is the same as this one, except the terminal value of the
 * returned channel is created by applying the specified function to the terminal value of this
 * channel.
 *
 * @ets_data_first map_
 */
function map(f) {
    return (self) => map_(self, f);
}
exports.map = map;
/**
 * Returns a new channel, which is the same as this one, except the failure value of the returned
 * channel is created by applying the specified function to the failure value of this channel.
 */
function mapError_(self, f) {
    return mapErrorCause_(self, (cause) => Cause.map_(cause, f));
}
exports.mapError_ = mapError_;
/**
 * Returns a new channel, which is the same as this one, except the failure value of the returned
 * channel is created by applying the specified function to the failure value of this channel.
 *
 * @ets_data_first mapError_
 */
function mapError(f) {
    return (self) => mapError_(self, f);
}
exports.mapError = mapError;
/**
 * A more powerful version of `mapError` which also surfaces the `Cause` of the channel failure
 */
function mapErrorCause_(self, f) {
    return catchAllCause_(self, (cause) => C.failCause(f(cause)));
}
exports.mapErrorCause_ = mapErrorCause_;
/**
 * A more powerful version of `mapError` which also surfaces the `Cause` of the channel failure
 *
 * @ets_data_first mapErrorCause_
 */
function mapErrorCause(f) {
    return (self) => mapErrorCause_(self, f);
}
exports.mapErrorCause = mapErrorCause;
function runManagedInterpret(channelState, exec) {
    // eslint-disable-next-line no-constant-condition
    while (1) {
        switch (channelState._typeId) {
            case executor_1.ChannelStateEffectTypeId: {
                return T.chain_(channelState.effect, () => runManagedInterpret(exec.run(), exec));
            }
            case executor_1.ChannelStateEmitTypeId: {
                channelState = exec.run();
                break;
            }
            case executor_1.ChannelStateDoneTypeId: {
                return T.done(exec.getDone());
            }
        }
    }
    throw new Error("Bug");
}
function toPullInterpret(channelState, exec) {
    switch (channelState._typeId) {
        case executor_1.ChannelStateEffectTypeId: {
            return T.chain_(T.mapError_(channelState.effect, E.left), () => toPullInterpret(exec.run(), exec));
        }
        case executor_1.ChannelStateEmitTypeId: {
            return T.succeed(exec.getEmit());
        }
        case executor_1.ChannelStateDoneTypeId: {
            const done = exec.getDone();
            if (done._tag === "Success") {
                return T.fail(E.right(done.value));
            }
            else {
                return T.halt(Cause.map_(done.cause, E.left));
            }
        }
    }
}
/**
 * Returns a new channel, which is the same as this one, except the terminal value of the
 * returned channel is created by applying the specified effectful function to the terminal value
 * of this channel.
 */
function mapEffect_(self, f) {
    return C.chain_(self, (z) => C.fromEffect(f(z)));
}
exports.mapEffect_ = mapEffect_;
/**
 * Returns a new channel, which is the same as this one, except the terminal value of the
 * returned channel is created by applying the specified effectful function to the terminal value
 * of this channel.
 *
 * @ets_data_first mapEffect_
 */
function mapEffect(f) {
    return (self) => mapEffect_(self, f);
}
exports.mapEffect = mapEffect;
/**
 * Returns a new channel, which is the merge of this channel and the specified channel, where
 * the behavior of the returned channel on left or right early termination is decided by the
 * specified `leftDone` and `rightDone` merge decisions.
 */
function mergeWith_(self, that, leftDone, rightDone) {
    const m = (M.map_(M.bind_(M.bind_(M.let_(M.bind_(M.do, "input", () => T.toManaged((0, producer_1.makeSingleProducerAsyncInput)())), "queueReader", ({ input }) => fromInput(input)), "pullL", ({ queueReader }) => toPull(queueReader[">>>"](self))), "pullR", ({ queueReader }) => toPull(queueReader[">>>"](that))), ({ input, pullL, pullR }) => {
        const handleSide = (exit, fiber, pull) => (done, both, single) => Ex.fold_(exit, (cause) => {
            const result = done(E.fold_(Cause.flipCauseEither(cause), (_) => Ex.halt(_), (_) => Ex.succeed(_)));
            MH.concrete(result);
            if (result._typeId === MH.DoneTypeId) {
                return T.succeed(C.fromEffect(T.zipRight_(F.interrupt(fiber), result.io)));
            }
            else if (result._typeId === MH.AwaitTypeId) {
                return T.map_(fiber.await, Ex.fold((cause) => C.fromEffect(result.f(E.fold_(Cause.flipCauseEither(cause), (_) => Ex.halt(_), (_) => Ex.succeed(_)))), (elem) => zipRight_(C.write(elem), go(single(result.f)))));
            }
            throw new Error("Unexpected");
        }, (elem) => T.map_(T.fork(pull), (leftFiber) => zipRight_(C.write(elem), go(both(leftFiber, fiber)))));
        const go = (state) => {
            if (state._typeId === MH.BothRunningTypeId) {
                const lj = F.join(state.left);
                const rj = F.join(state.right);
                return C.unwrap(T.raceWith_(lj, rj, (leftEx, _) => handleSide(leftEx, state.right, pullL)(leftDone, (l, r) => new MH.BothRunning(l, r), (_) => new MH.LeftDone(_)), (rightEx, _) => handleSide(rightEx, state.left, pullR)(rightDone, (l, r) => new MH.BothRunning(r, l), (_) => new MH.RightDone(_))));
            }
            else if (state._typeId === MH.LeftDoneTypeId) {
                return C.unwrap(T.map_(T.result(pullR), Ex.fold((cause) => C.fromEffect(state.f(E.fold_(Cause.flipCauseEither(cause), (_) => Ex.halt(_), (_) => Ex.succeed(_)))), (elem) => zipRight_(C.write(elem), go(new MH.LeftDone(state.f))))));
            }
            else {
                return C.unwrap(T.map_(T.result(pullL), Ex.fold((cause) => C.fromEffect(state.f(E.fold_(Cause.flipCauseEither(cause), (_) => Ex.halt(_), (_) => Ex.succeed(_)))), (elem) => zipRight_(C.write(elem), go(new MH.RightDone(state.f))))));
            }
        };
        return (C.embedInput_(C.chain_(C.fromEffect(T.zipWith_(T.fork(pullL), T.fork(pullR), (a, b) => new MH.BothRunning(a, b))), go), input));
    }));
    return C.unwrapManaged(m);
}
exports.mergeWith_ = mergeWith_;
/**
 * Returns a new channel, which is the merge of this channel and the specified channel, where
 * the behavior of the returned channel on left or right early termination is decided by the
 * specified `leftDone` and `rightDone` merge decisions.
 *
 * @ets_data_first mergeWith_
 */
function mergeWith(that, leftDone, rightDone) {
    return (self) => mergeWith_(self, that, leftDone, rightDone);
}
exports.mergeWith = mergeWith;
/**
 * Maps the output of this channel using f
 */
function mapOut_(self, f) {
    const reader = C.readWithCause((i) => C.chain_(C.write(f(i)), () => reader), C.failCause, C.end);
    return self[">>>"](reader);
}
exports.mapOut_ = mapOut_;
/**
 * Maps the output of this channel using f
 *
 * @ets_data_first mapOut_
 */
function mapOut(f) {
    return (self) => mapOut_(self, f);
}
exports.mapOut = mapOut;
const mapOutMReader = (f) => C.readWith((out) => C.chain_(C.fromEffect(f(out)), (_) => zipRight_(C.write(_), mapOutMReader(f))), (e) => C.fail(e), (z) => C.end(z));
function mapOutEffect_(self, f) {
    return C.pipeTo_(self, mapOutMReader(f));
}
exports.mapOutEffect_ = mapOutEffect_;
/**
 * @ets_data_first mapOutEffect_
 */
function mapOutEffect(f) {
    return (self) => mapOutEffect_(self, f);
}
exports.mapOutEffect = mapOutEffect;
exports.never = C.fromEffect(T.never);
function orDie_(self, err) {
    return orDieWith_(self, (_) => err);
}
exports.orDie_ = orDie_;
/**
 * @ets_data_first orDie_
 */
function orDie(err) {
    return (self) => orDie_(self, err);
}
exports.orDie = orDie;
function orDieWith_(self, f) {
    return catchAll_(self, (e) => C.die(f(e)));
}
exports.orDieWith_ = orDieWith_;
/**
 * @ets_data_first orDieWith_
 */
function orDieWith(f) {
    return (self) => orDieWith_(self, f);
}
exports.orDieWith = orDieWith;
/**
 * Repeats this channel forever
 */
function repeated(self) {
    return C.chain_(self, () => repeated(self));
}
exports.repeated = repeated;
/**
 * Runs a channel until the end is received
 */
function runManaged(self) {
    return M.mapM_(M.makeExit_(T.succeedWith(() => new executor_1.ChannelExecutor(() => self, undefined)), (exec, exit) => exec.close(exit) || T.unit), (exec) => T.suspend(() => runManagedInterpret(exec.run(), exec)));
}
exports.runManaged = runManaged;
/**
 * Runs a channel until the end is received
 */
function run(self) {
    return M.useNow(runManaged(self));
}
exports.run = run;
function runCollect(self) {
    return run(doneCollect(self));
}
exports.runCollect = runCollect;
/**
 * Runs a channel until the end is received
 */
function runDrain(self) {
    return run(C.drain(self));
}
exports.runDrain = runDrain;
function unit_(self) {
    return as_(self, undefined);
}
exports.unit_ = unit_;
/**
 * Interpret a channel to a managed Pull
 */
function toPull(self) {
    return M.map_(M.makeExit_(T.succeedWith(() => new executor_1.ChannelExecutor(() => self, undefined)), (exec, exit) => exec.close(exit) || T.unit), (exec) => T.suspend(() => toPullInterpret(exec.run(), exec)));
}
exports.toPull = toPull;
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with a tuple of the terminal values of both channels.
 */
function zip_(self, that) {
    return C.chain_(self, (z) => map_(that, (z2) => Tp.tuple(z, z2)));
}
exports.zip_ = zip_;
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with a tuple of the terminal values of both channels.
 *
 * @ets_data_first zip_
 */
function zip(that) {
    return (self) => zip_(self, that);
}
exports.zip = zip;
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with the terminal value of this channel.
 */
function zipLeft_(self, that) {
    return map_(zip_(self, that), Tp.get(0));
}
exports.zipLeft_ = zipLeft_;
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with the terminal value of this channel.
 *
 * @ets_data_first zipLeft_
 */
function zipLeft(that) {
    return (self) => zipLeft_(self, that);
}
exports.zipLeft = zipLeft;
function zipPar_(self, that) {
    return mergeWith_(self, that, (exit1) => MH.await_((exit2) => T.done(Ex.zip_(exit1, exit2))), (exit2) => MH.await_((exit1) => T.done(Ex.zip_(exit1, exit2))));
}
exports.zipPar_ = zipPar_;
/**
 * @ets_data_first zipPar_
 */
function zipPar(that) {
    return (self) => zipPar_(self, that);
}
exports.zipPar = zipPar;
function zipParLeft_(self, that) {
    return map_(zipPar_(self, that), Tp.get(0));
}
exports.zipParLeft_ = zipParLeft_;
/**
 * @ets_data_first zipParLeft_
 */
function zipParLeft(that) {
    return (self) => zipParLeft_(self, that);
}
exports.zipParLeft = zipParLeft;
function zipParRight_(self, that) {
    return map_(zipPar_(self, that), Tp.get(1));
}
exports.zipParRight_ = zipParRight_;
/**
 * @ets_data_first zipParRight_
 */
function zipParRight(that) {
    return (self) => zipParRight_(self, that);
}
exports.zipParRight = zipParRight;
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with the terminal value of the other channel.
 */
function zipRight_(self, that) {
    return map_(zip_(self, that), Tp.get(1));
}
exports.zipRight_ = zipRight_;
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with the terminal value of the other channel.
 *
 * @ets_data_first zipRight_
 */
function zipRight(that) {
    return (self) => zipRight_(self, that);
}
exports.zipRight = zipRight;
function bracketOut_(acquire, release) {
    return C.bracketOutExit_(acquire, (z, _) => release(z));
}
exports.bracketOut_ = bracketOut_;
/**
 * @ets_data_first bracketOut_
 */
function bracketOut(release) {
    return (acquire) => bracketOut_(acquire, release);
}
exports.bracketOut = bracketOut;
function bracket_(acquire, use, release) {
    return bracketExit_(acquire, use, (a, _) => release(a));
}
exports.bracket_ = bracket_;
/**
 * @ets_data_first bracket_
 */
function bracket(use, release) {
    return (acquire) => bracket_(acquire, use, release);
}
exports.bracket = bracket;
function bracketExit_(acquire, use, release) {
    return (C.chain_(C.fromEffect(Ref.makeRef((_) => T.unit)), (ref) => (C.ensuringWith_(C.chain_(C.fromEffect(T.uninterruptible(T.tap_(acquire, (a) => ref.set((_) => release(a, _))))), use), (ex) => T.chain_(ref.get, (_) => _(ex))))));
}
exports.bracketExit_ = bracketExit_;
/**
 * @ets_data_first bracketExit_
 */
function bracketExit(use, release) {
    return (acquire) => bracketExit_(acquire, use, release);
}
exports.bracketExit = bracketExit;
/**
 * Creates a channel backed by a buffer. When the buffer is empty, the channel will simply
 * passthrough its input as output. However, when the buffer is non-empty, the value inside
 * the buffer will be passed along as output.
 */
function buffer(empty, isEmpty, ref) {
    return C.unwrap(Ref.modify_(ref, (v) => {
        if (isEmpty(v)) {
            return Tp.tuple(C.readWith((_in) => zipRight_(C.write(_in), buffer(empty, isEmpty, ref)), (err) => C.fail(err), (done) => C.end(done)), v);
        }
        else {
            return Tp.tuple(zipRight_(C.write(v), buffer(empty, isEmpty, ref)), empty);
        }
    }));
}
exports.buffer = buffer;
function bufferChunk(ref) {
    return buffer(A.empty(), (_) => A.isEmpty(_), ref);
}
exports.bufferChunk = bufferChunk;
function concatAll(channels) {
    return C.concatAllWith_(channels, (_, __) => void 0, (_, __) => void 0);
}
exports.concatAll = concatAll;
function fromEither(either) {
    return E.fold_(either, C.fail, succeed);
}
exports.fromEither = fromEither;
function fromOption(option) {
    return O.fold_(option, () => C.fail(O.none), (_) => succeed(_));
}
exports.fromOption = fromOption;
function identity() {
    return C.readWith((_in) => zipRight_(C.write(_in), identity()), (err) => C.fail(err), (done) => C.end(done));
}
exports.identity = identity;
function interrupt(fiberId) {
    return C.failCause(Cause.interrupt(fiberId));
}
exports.interrupt = interrupt;
function managed_(m, use) {
    return bracket_(RM.makeReleaseMap, (releaseMap) => {
        return (C.chain_(C.fromEffect((T.map_(T.provideSome_(m.effect, (_) => Tp.tuple(_, releaseMap)), Tp.get(1)))), use));
    }, (_) => RM.releaseAll(Ex.unit, // FIXME: BracketOut should be BracketOutExit (From ZIO)
    Effect_1.sequential)(_));
}
exports.managed_ = managed_;
/**
 * @ets_data_first managed_
 */
function managed(use) {
    return (m) => managed_(m, use);
}
exports.managed = managed;
function readOrFail(e) {
    return new P.Read((in_) => C.end(in_), new P.ContinuationK((_) => C.fail(e), (_) => C.fail(e)));
}
exports.readOrFail = readOrFail;
function read() {
    return readOrFail(O.none);
}
exports.read = read;
function succeed(z) {
    return C.end(z);
}
exports.succeed = succeed;
function fromHub(hub) {
    return managed_(H.subscribe(hub), fromQueue);
}
exports.fromHub = fromHub;
function fromInput(input) {
    return C.unwrap(input.takeWith((_) => C.failCause(_), (_) => zipRight_(C.write(_), fromInput(input)), (_) => C.end(_)));
}
exports.fromInput = fromInput;
function fromQueue(queue) {
    return C.chain_(C.fromEffect(Q.take(queue)), Ex.fold((cause) => E.fold_(Cause.flipCauseEither(cause), (cause) => C.failCause(cause), (done) => C.end(done)), (elem) => zipRight_(C.write(elem), fromQueue(queue))));
}
exports.fromQueue = fromQueue;
function toHub(hub) {
    return toQueue(H.toQueue(hub));
}
exports.toHub = toHub;
function toQueue(queue) {
    return C.readWithCause((in_) => zipRight_(C.fromEffect(Q.offer_(queue, Ex.succeed(in_))), toQueue(queue)), (cause) => C.fromEffect(Q.offer_(queue, Ex.halt(Cause.map_(cause, (_) => E.left(_))))), (done) => C.fromEffect(Q.offer_(queue, Ex.fail(E.right(done)))));
}
exports.toQueue = toQueue;
function writeAll(...outs) {
    return AR.reduceRight_(outs, C.end(undefined), (out, conduit) => zipRight_(C.write(out), conduit));
}
exports.writeAll = writeAll;
function writeChunk(outs) {
    const writer = (idx, len) => idx === len
        ? C.unit
        : zipRight_(C.write(A.unsafeGet_(outs, idx)), writer(idx + 1, len));
    return writer(0, A.size(outs));
}
exports.writeChunk = writeChunk;
//# sourceMappingURL=api.js.map