import "../../../../Operator"
import * as Cause from "../../../../Cause"
import * as T from "../../../../Effect"
import * as E from "../../../../Either"
import * as Exit from "../../../../Exit"
import * as P from "../../../../Promise"
import * as Ref from "../../../../Ref"
/**
 * Producer-side view of `SingleProducerAsyncInput` for variance purposes.
 */
export interface AsyncInputProducer<Err, Elem, Done> {
  emit(el: Elem): T.UIO<unknown>
  done(a: Done): T.UIO<unknown>
  error(cause: Cause.Cause<Err>): T.UIO<unknown>
}
/**
 * Consumer-side view of `SingleProducerAsyncInput` for variance purposes.
 */
export interface AsyncInputConsumer<Err, Elem, Done> {
  takeWith<A>(
    onError: (cause: Cause.Cause<Err>) => A,
    onElement: (element: Elem) => A,
    onDone: (done: Done) => A
  ): T.UIO<A>
}
export declare const DoneTypeId: unique symbol
export declare type DoneTypeId = typeof DoneTypeId
export declare class StateDone<A> {
  readonly a: A
  readonly _typeId: DoneTypeId
  constructor(a: A)
}
export declare const ErrorTypeId: unique symbol
export declare type ErrorTypeId = typeof ErrorTypeId
export declare class StateError<E> {
  readonly cause: Cause.Cause<E>
  readonly _typeId: ErrorTypeId
  constructor(cause: Cause.Cause<E>)
}
export declare const EmptyTypeId: unique symbol
export declare type EmptyTypeId = typeof EmptyTypeId
export declare class StateEmpty {
  readonly notifyConsumer: P.Promise<never, void>
  readonly _typeId: EmptyTypeId
  constructor(notifyConsumer: P.Promise<never, void>)
}
export declare const EmitTypeId: unique symbol
export declare type EmitTypeId = typeof EmitTypeId
export declare class StateEmit<Elem> {
  readonly a: Elem
  readonly notifyProducer: P.Promise<never, void>
  readonly _typeId: EmitTypeId
  constructor(a: Elem, notifyProducer: P.Promise<never, void>)
}
export declare type State<Err, Elem, Done> =
  | StateEmpty
  | StateEmit<Elem>
  | StateError<Err>
  | StateDone<Done>
/**
 * An MVar-like abstraction for sending data to channels asynchronously. Designed
 * for one producer and multiple consumers.
 *
 * Features the following semantics:
 * - Buffer of size 1
 * - When emitting, the producer waits for a consumer to pick up the value
 *   to prevent "reading ahead" too much.
 * - Once an emitted element is read by a consumer, it is cleared from the buffer, so that
 *   at most one consumer sees every emitted element.
 * - When sending a done or error signal, the producer does not wait for a consumer
 *   to pick up the signal. The signal stays in the buffer after being read by a consumer,
 *   so it can be propagated to multiple consumers.
 * - Trying to publish another emit/error/done after an error/done have already been published
 *   results in an interruption.
 */
export declare class SingleProducerAsyncInput<Err, Elem, Done>
  implements AsyncInputProducer<Err, Elem, Done>, AsyncInputConsumer<Err, Elem, Done>
{
  readonly ref: Ref.Ref<State<Err, Elem, Done>>
  constructor(ref: Ref.Ref<State<Err, Elem, Done>>)
  emit(el: Elem): T.UIO<unknown>
  done(a: Done): T.UIO<unknown>
  error(cause: Cause.Cause<Err>): T.UIO<unknown>
  takeWith<X>(
    onError: (cause: Cause.Cause<Err>) => X,
    onElement: (element: Elem) => X,
    onDone: (done: Done) => X
  ): T.UIO<X>
  take: T.UIO<Exit.Exit<E.Either<Err, Done>, Elem>>
  close: T.Effect<unknown, never, unknown>
}
/**
 * Creates a SingleProducerAsyncInput
 */
export declare function makeSingleProducerAsyncInput<Err, Elem, Done>(): T.UIO<
  SingleProducerAsyncInput<Err, Elem, Done>
>
//# sourceMappingURL=producer.d.ts.map
