export type Thunk<R = void> = () => R;
export type Undo = Thunk<void>;
export type Done = (err?: unknown) => void;
export type Read<T> = (result: IteratorResult<T>) => void;
export type Write<T> = {
    value: T;
    enqueued?: Done;
    written?: Done;
};
export declare class AttemptBase {
}
export declare class ReadAttempt<T, R> extends AttemptBase {
    readonly channel: Channel<T>;
    readonly perform: (result: IteratorResult<T>) => IteratorResult<R>;
    constructor(channel: Channel<T>, perform: (result: IteratorResult<T>) => IteratorResult<R>);
}
export declare class WriteAttempt<T, R> extends AttemptBase {
    readonly channel: Channel<T>;
    readonly value: T;
    readonly perform: (value: T) => IteratorResult<R>;
    constructor(channel: Channel<T>, value: T, perform: (value: T) => IteratorResult<R>);
}
export type Attempt = Channel<any> | ReadAttempt<any, any> | WriteAttempt<any, any>;
export type Attempted<A extends Attempt> = A extends Channel<infer T> ? T : A extends ReadAttempt<any, infer R> ? R : A extends WriteAttempt<any, infer R> ? R : never;
export declare class Channel<T> implements AsyncIterableIterator<T> {
    #private;
    constructor(cap?: number);
    get cap(): number;
    /** @returns number of pending reads. */
    get pendingReads(): number;
    /** @returns number of pending writes. */
    get pendingWrites(): number;
    [Symbol.asyncIterator](): this;
    return(value?: any): Promise<{
        done: boolean;
        value: any;
    }>;
    throw(err?: any): Promise<{
        done: boolean;
        value: any;
    }>;
    /** @returns `true` if channels has been closed and there are no pending writes. */
    get done(): boolean;
    /** @returns  */
    get doneWriting(): boolean;
    /**
     * Closes writing only.
     *
     * Writes beyond capacity are settled with optional err.
     *
     * If there are no pending writes channel is effectively done - closed for reading and writing.
     *
     * @see {@link close} for closing channel for reading and writing.
     */
    closeWriting(err?: unknown): void;
    /**
     * Closes channel for both reading and writing.
     *
     * @see {@link closeWriting} for closing channel for writing only.
     */
    close(err?: unknown): void;
    /**
     * Registers callback to be called when channel has done writing.
     * Callback is called immediatelly if channel is already closed for writing.
     * @returns undo function that unregisters callback.
     */
    onceDoneWriting(done: Done): Undo;
    next(): Promise<IteratorResult<T>>;
    /** @throws if channel is closed. */
    read(): Promise<T>;
    maybeRead(): Promise<undefined | T>;
    /** @returns all values that was possible to read immediatelly, aka all pending writes. */
    consumeWrites(): T[];
    readAttempt<R>(perform: (result: IteratorResult<T>) => IteratorResult<R>): ReadAttempt<T, R>;
    write(value: T): Promise<void>;
    maybeWrite(value: T): Promise<boolean>;
    writeIgnore(value: T): void;
    writeAttempt<R>(value: T, perform: (value: T) => IteratorResult<R>): WriteAttempt<T, R>;
    /**
     * Pushes read to the channel.
     * @returns undo operation.
     */
    pushRead(read: Read<T>): Undo;
    /**
     * Pushes write to the channel.
     * @returns undo operation.
     */
    pushWrite(write: Write<T>): Undo;
    consumeRead(result: IteratorResult<T>): void;
    consumeWrite(): T;
}
