import { Uint8ArrayList } from 'uint8arraylist';
import type { MessageStream, Stream, AbortOptions } from '@libp2p/interface';
import type { Duplex, Transform, Sink } from 'it-stream-types';
export declare class UnwrappedError extends Error {
    static name: string;
    name: string;
}
/**
 * The reported length of the next data message was not a positive integer
 */
export declare class InvalidMessageLengthError extends Error {
    name: string;
    code: string;
}
/**
 * The reported length of the next data message was larger than the configured
 * max allowable value
 */
export declare class InvalidDataLengthError extends Error {
    name: string;
    code: string;
}
/**
 * The varint used to specify the length of the next data message contained more
 * bytes than the configured max allowable value
 */
export declare class InvalidDataLengthLengthError extends Error {
    name: string;
    code: string;
}
export interface ByteStreamOpts {
    /**
     * Incoming bytes are buffered until read, this setting limits how many bytes
     * will be buffered.
     *
     * @default 4_194_304
     */
    maxBufferSize?: number;
}
export interface ReadBytesOptions extends AbortOptions {
    /**
     * If specified, read this number of bytes from the stream
     */
    bytes: number;
}
export interface ByteStream<S extends MessageStream> {
    /**
     * Read bytes from the stream.
     *
     * If a required number of bytes is passed as an option, this will wait for
     * the underlying stream to supply that number of bytes, throwing an
     * `UnexpectedEOFError` if the stream closes before this happens.
     *
     * If no required number of bytes is passed, this will return `null` if the
     * underlying stream closes before supplying any bytes.
     */
    read(options: ReadBytesOptions): Promise<Uint8ArrayList>;
    read(options?: AbortOptions): Promise<Uint8ArrayList | null>;
    /**
     * Write the passed bytes to the stream
     */
    write(data: Uint8Array | Uint8ArrayList, options?: AbortOptions): Promise<void>;
    /**
     * After calling this method the stream can no longer be used. Any unread data
     * will be emitted as a message event during the microtask queue of the
     * current event loop tick.
     */
    unwrap(): S;
}
export declare function byteStream<T extends MessageStream>(stream: T, opts?: ByteStreamOpts): ByteStream<T>;
export interface LengthPrefixedStream<S extends MessageStream = MessageStream> {
    /**
     * Read the next length-prefixed number of bytes from the stream
     */
    read(options?: AbortOptions): Promise<Uint8ArrayList>;
    /**
     * Write the passed bytes to the stream prefixed by their length
     */
    write(data: Uint8Array | Uint8ArrayList, options?: AbortOptions): Promise<void>;
    /**
     * Write passed list of bytes, prefix by their individual lengths to the stream as a single write
     */
    writeV(input: Array<Uint8Array | Uint8ArrayList>, options?: AbortOptions): Promise<void>;
    /**
     * Returns the underlying stream
     */
    unwrap(): S;
}
export interface LengthPrefixedStreamOpts extends ByteStreamOpts {
    lengthEncoder(value: number): Uint8ArrayList | Uint8Array;
    lengthDecoder(data: Uint8ArrayList): number;
    maxLengthLength: number;
    maxDataLength: number;
}
export declare function lpStream<T extends MessageStream>(stream: T, opts?: Partial<LengthPrefixedStreamOpts>): LengthPrefixedStream<T>;
/**
 * A protobuf decoder - takes a byte array and returns an object
 */
export interface ProtobufDecoder<T> {
    (data: Uint8Array | Uint8ArrayList): T;
}
/**
 * A protobuf encoder - takes an object and returns a byte array
 */
export interface ProtobufEncoder<T> {
    (data: T): Uint8Array;
}
/**
 * Convenience methods for working with protobuf streams
 */
export interface ProtobufStream<S extends MessageStream = MessageStream> {
    /**
     * Read the next length-prefixed byte array from the stream and decode it as the passed protobuf format
     */
    read<T>(proto: {
        decode: ProtobufDecoder<T>;
    }, options?: AbortOptions): Promise<T>;
    /**
     * Encode the passed object as a protobuf message and write it's length-prefixed bytes to the stream
     */
    write<T>(data: T, proto: {
        encode: ProtobufEncoder<T>;
    }, options?: AbortOptions): Promise<void>;
    /**
     * Encode the passed objects as protobuf messages and write their length-prefixed bytes to the stream as a single write
     */
    writeV<T>(input: T[], proto: {
        encode: ProtobufEncoder<T>;
    }, options?: AbortOptions): Promise<void>;
    /**
     * Returns an object with read/write methods for operating on one specific type of protobuf message
     */
    pb<T>(proto: {
        encode: ProtobufEncoder<T>;
        decode: ProtobufDecoder<T>;
    }): ProtobufMessageStream<T, S>;
    /**
     * Returns the underlying stream
     */
    unwrap(): S;
}
/**
 * A message reader/writer that only uses one type of message
 */
export interface ProtobufMessageStream<T, S extends MessageStream = MessageStream> {
    /**
     * Read a message from the stream
     */
    read(options?: AbortOptions): Promise<T>;
    /**
     * Write a message to the stream
     */
    write(d: T, options?: AbortOptions): Promise<void>;
    /**
     * Write several messages to the stream
     */
    writeV(d: T[], options?: AbortOptions): Promise<void>;
    /**
     * Unwrap the underlying protobuf stream
     */
    unwrap(): ProtobufStream<S>;
}
export interface ProtobufStreamOpts extends LengthPrefixedStreamOpts {
}
export declare function pbStream<T extends MessageStream = Stream>(stream: T, opts?: Partial<ProtobufStreamOpts>): ProtobufStream<T>;
export declare function echo(stream: MessageStream, options?: AbortOptions): Promise<void>;
export type PipeInput = Iterable<Uint8Array | Uint8ArrayList> | AsyncIterable<Uint8Array | Uint8ArrayList> | Stream;
export declare function messageStreamToDuplex(stream: Stream): Duplex<AsyncGenerator<Uint8ArrayList | Uint8Array>, Iterable<Uint8ArrayList | Uint8Array> | AsyncIterable<Uint8ArrayList | Uint8Array>, Promise<void>>;
interface SourceFn<A = any> {
    (): A;
}
type PipeSource<A = any> = Iterable<A> | AsyncIterable<A> | SourceFn<A> | Duplex<A, any, any> | MessageStream;
type PipeTransform<A = any, B = any> = Transform<A, B> | Duplex<B, A> | MessageStream;
type PipeSink<A = any, B = any> = Sink<A, B> | Duplex<any, A, B> | MessageStream;
type PipeOutput<A> = A extends Sink<any> ? ReturnType<A> : A extends Duplex<any, any, any> ? ReturnType<A['sink']> : A extends MessageStream ? Promise<void> : never;
type SingleItemPipeOutput<A> = A extends Iterable<any> ? A : A extends AsyncIterable<any> ? A : A extends SourceFn ? ReturnType<A> : A extends Duplex<any, any, any> ? A['source'] : PipeOutput<A>;
type PipeFnInput<A> = A extends Iterable<any> ? A : A extends AsyncIterable<any> ? A : A extends SourceFn ? ReturnType<A> : A extends Transform<any, any> ? ReturnType<A> : A extends Duplex<any, any, any> ? A['source'] : never;
export declare function pipe<A extends PipeSource>(source: A): SingleItemPipeOutput<A>;
export declare function pipe<A extends PipeSource, B extends PipeSink<PipeFnInput<A>>>(source: A, sink: B): PipeOutput<B>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeSink<PipeFnInput<B>>>(source: A, transform1: B, sink: C): PipeOutput<C>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeTransform<PipeFnInput<B>>, D extends PipeSink<PipeFnInput<C>>>(source: A, transform1: B, transform2: C, sink: D): PipeOutput<D>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeTransform<PipeFnInput<B>>, D extends PipeTransform<PipeFnInput<C>>, E extends PipeSink<PipeFnInput<D>>>(source: A, transform1: B, transform2: C, transform3: D, sink: E): PipeOutput<E>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeTransform<PipeFnInput<B>>, D extends PipeTransform<PipeFnInput<C>>, E extends PipeTransform<PipeFnInput<D>>, F extends PipeSink<PipeFnInput<E>>>(source: A, transform1: B, transform2: C, transform3: D, transform4: E, sink: F): PipeOutput<F>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeTransform<PipeFnInput<B>>, D extends PipeTransform<PipeFnInput<C>>, E extends PipeTransform<PipeFnInput<D>>, F extends PipeTransform<PipeFnInput<E>>, G extends PipeSink<PipeFnInput<F>>>(source: A, transform1: B, transform2: C, transform3: D, transform4: E, transform5: F, sink: G): PipeOutput<G>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeTransform<PipeFnInput<B>>, D extends PipeTransform<PipeFnInput<C>>, E extends PipeTransform<PipeFnInput<D>>, F extends PipeTransform<PipeFnInput<E>>, G extends PipeTransform<PipeFnInput<F>>, H extends PipeSink<PipeFnInput<G>>>(source: A, transform1: B, transform2: C, transform3: D, transform4: E, transform5: F, transform6: G, sink: H): PipeOutput<H>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeTransform<PipeFnInput<B>>, D extends PipeTransform<PipeFnInput<C>>, E extends PipeTransform<PipeFnInput<D>>, F extends PipeTransform<PipeFnInput<E>>, G extends PipeTransform<PipeFnInput<F>>, H extends PipeTransform<PipeFnInput<G>>, I extends PipeSink<PipeFnInput<H>>>(source: A, transform1: B, transform2: C, transform3: D, transform4: E, transform5: F, transform6: G, transform7: H, sink: I): PipeOutput<I>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeTransform<PipeFnInput<B>>, D extends PipeTransform<PipeFnInput<C>>, E extends PipeTransform<PipeFnInput<D>>, F extends PipeTransform<PipeFnInput<E>>, G extends PipeTransform<PipeFnInput<F>>, H extends PipeTransform<PipeFnInput<G>>, I extends PipeTransform<PipeFnInput<H>>, J extends PipeSink<PipeFnInput<I>>>(source: A, transform1: B, transform2: C, transform3: D, transform4: E, transform5: F, transform6: G, transform7: H, transform8: I, sink: J): PipeOutput<J>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeTransform<PipeFnInput<B>>, D extends PipeTransform<PipeFnInput<C>>, E extends PipeTransform<PipeFnInput<D>>, F extends PipeTransform<PipeFnInput<E>>, G extends PipeTransform<PipeFnInput<F>>, H extends PipeTransform<PipeFnInput<G>>, I extends PipeTransform<PipeFnInput<H>>, J extends PipeTransform<PipeFnInput<I>>, K extends PipeSink<PipeFnInput<J>>>(source: A, transform1: B, transform2: C, transform3: D, transform4: E, transform5: F, transform6: G, transform7: H, transform8: I, transform9: J, sink: K): PipeOutput<K>;
export declare function pipe<A extends PipeSource, B extends PipeTransform<PipeFnInput<A>>, C extends PipeTransform<PipeFnInput<B>>, D extends PipeTransform<PipeFnInput<C>>, E extends PipeTransform<PipeFnInput<D>>, F extends PipeTransform<PipeFnInput<E>>, G extends PipeTransform<PipeFnInput<F>>, H extends PipeTransform<PipeFnInput<G>>, I extends PipeTransform<PipeFnInput<H>>, J extends PipeTransform<PipeFnInput<I>>, K extends PipeTransform<PipeFnInput<J>>, L extends PipeSink<PipeFnInput<K>>>(source: A, transform1: B, transform2: C, transform3: D, transform4: E, transform5: F, transform6: G, transform7: H, transform8: I, transform9: J, transform10: K, sink: L): PipeOutput<L>;
export {};
//# sourceMappingURL=stream-utils.d.ts.map