import { Duplex, PassThrough, Transform, type Readable } from "../../stream/index.js";
import { ByteQueue } from "../internal/byte-queue.js";
import { parseZipExtraFields, type ZipExtraFields, type ZipVars } from "../utils/zip-extra-fields.js";
export declare const DATA_DESCRIPTOR_SIGNATURE_BYTES: Uint8Array<ArrayBufferLike>;
export declare const CRX_HEADER_FORMAT: [string, number][];
export declare const LOCAL_FILE_HEADER_FORMAT: [string, number][];
export declare const DATA_DESCRIPTOR_FORMAT: [string, number][];
export declare const CENTRAL_DIRECTORY_FILE_HEADER_FORMAT: [string, number][];
export declare const END_OF_CENTRAL_DIRECTORY_FORMAT: [string, number][];
export interface ZipEntryVarsMeta {
    flags: number | null;
    uncompressedSize: number;
    lastModifiedDate: number | null;
    lastModifiedTime: number | null;
}
export type { ZipVars, ZipExtraFields };
export interface ZipEntryPropsMeta {
    path: string;
    pathBuffer: Uint8Array;
    flags: {
        isUnicode: boolean;
    };
}
export interface CrxHeader {
    version: number | null;
    pubKeyLength: number | null;
    signatureLength: number | null;
    publicKey?: Uint8Array;
    signature?: Uint8Array;
}
export interface LocalFileHeaderVars {
    versionsNeededToExtract: number | null;
    flags: number | null;
    compressionMethod: number | null;
    lastModifiedTime: number | null;
    lastModifiedDate: number | null;
    crc32: number | null;
    compressedSize: number | null;
    uncompressedSize: number | null;
    fileNameLength: number | null;
    extraFieldLength: number | null;
}
export interface DataDescriptorVars {
    dataDescriptorSignature: number | null;
    crc32: number | null;
    compressedSize: number | null;
    uncompressedSize: number | null;
}
export declare function decodeZipEntryPath(pathBuffer: Uint8Array): string;
export declare function isZipUnicodeFlag(flags: number | null): boolean;
export declare function isZipDirectoryPath(path: string): boolean;
export declare function getZipEntryType(path: string, uncompressedSize: number): "Directory" | "File";
export declare function buildZipEntryProps(path: string, pathBuffer: Uint8Array, flags: number | null): ZipEntryPropsMeta;
export declare function resolveZipEntryLastModifiedDateTime(vars: ZipEntryVarsMeta, extraFields: ZipExtraFields): Date;
export declare const parseExtraField: typeof parseZipExtraFields;
export declare function hasDataDescriptorFlag(flags: number | null): boolean;
export declare function isFileSizeKnown(flags: number | null, compressedSize: number | null): boolean;
export type DrainStream = Transform & {
    promise: () => Promise<void>;
};
export declare function autodrain(stream: {
    pipe: (dest: Transform) => unknown;
}): DrainStream;
/**
 * Collects all data from a readable stream into a single Uint8Array.
 */
export declare function bufferStream(entry: Readable): Promise<Uint8Array>;
export type PullFn = (length: number) => Promise<Uint8Array>;
export declare class PullStream extends Duplex {
    protected readonly _queue: ByteQueue;
    get buffer(): Uint8Array;
    set buffer(value: Uint8Array);
    cb?: () => void;
    finished: boolean;
    match?: number;
    __emittedError?: Error;
    constructor();
    _write(chunk: Uint8Array | string, _encoding: string, callback: () => void): void;
    _read(): void;
    protected _maybeReleaseWriteCallback(): void;
    /**
     * The `eof` parameter is interpreted as `file_length` if the type is number
     * otherwise (i.e. Uint8Array) it is interpreted as a pattern signaling end of stream
     */
    stream(eof: number | Uint8Array, includeEof?: boolean): PassThrough;
    pull(eof: number | Uint8Array, includeEof?: boolean): Promise<Uint8Array>;
    pullUntil(pattern: Uint8Array, includeEof?: boolean): Promise<Uint8Array>;
}
export type PullStreamPublicApi = {
    buffer: Uint8Array;
    cb?: () => void;
    finished: boolean;
    match?: number;
    stream(eof: number | Uint8Array, includeEof?: boolean): PassThrough;
    pull(eof: number | Uint8Array, includeEof?: boolean): Promise<Uint8Array>;
    pullUntil(pattern: Uint8Array, includeEof?: boolean): Promise<Uint8Array>;
};
export declare function readCrxHeader(pull: PullFn): Promise<CrxHeader>;
export declare function readLocalFileHeader(pull: PullFn): Promise<{
    vars: EntryVars;
    fileNameBuffer: Uint8Array;
    extraFieldData: Uint8Array;
}>;
export declare function readDataDescriptor(pull: PullFn): Promise<DataDescriptorVars>;
export declare function consumeCentralDirectoryFileHeader(pull: PullFn): Promise<void>;
export declare function consumeEndOfCentralDirectoryRecord(pull: PullFn): Promise<void>;
export interface ValidatedDataDescriptorScanResult {
    /** Start index of the descriptor within `view`, or -1 when not found yet. */
    foundIndex: number;
    /** Where the caller should resume searching on the next scan of (a mostly unchanged) view. */
    nextSearchFrom: number;
}
/**
 * Scan for a validated DATA_DESCRIPTOR record boundary.
 *
 * Scanning for the 4-byte signature alone is unsafe because it can appear inside
 * compressed data. We validate a candidate by requiring:
 * - the next 4 bytes after the 16-byte descriptor form a known ZIP record signature, and
 * - the descriptor's compressedSize matches the number of compressed bytes emitted so far.
 */
export declare function scanValidatedDataDescriptor(view: Uint8Array, dataDescriptorSignature: Uint8Array, bytesEmitted: number, startIndex?: number, out?: ValidatedDataDescriptorScanResult): ValidatedDataDescriptorScanResult;
export interface StreamUntilValidatedDataDescriptorSource {
    getLength(): number;
    read(length: number): Uint8Array;
    /** Optional: zero-copy chunk views for streaming writes. */
    peekChunks?(length: number): Uint8Array[];
    /** Optional: consume bytes previously written from peekChunks(). */
    discard?(length: number): void;
    indexOfPattern(pattern: Uint8Array, startIndex: number): number;
    peekUint32LE(offset: number): number | null;
    isFinished(): boolean;
    onDataAvailable(cb: () => void): () => void;
    maybeReleaseWriteCallback?: () => void;
}
export interface StreamUntilValidatedDataDescriptorOptions {
    source: StreamUntilValidatedDataDescriptorSource;
    dataDescriptorSignature: Uint8Array;
    /** Keep enough bytes to validate: descriptor(16) + next record sig(4) = 20. */
    keepTailBytes?: number;
    errorMessage?: string;
}
/**
 * Stream compressed file data until we reach a validated DATA_DESCRIPTOR boundary.
 *
 * This encapsulates the shared logic used by both Node and browser parsers.
 */
export declare function streamUntilValidatedDataDescriptor(options: StreamUntilValidatedDataDescriptorOptions): PassThrough;
export interface ParseOptions {
    verbose?: boolean;
    forceStream?: boolean;
    /**
     * Browser-only: use a Web Worker to run inflate off the main thread.
     * Defaults to false.
     */
    useWorkerInflate?: boolean;
    /**
     * Browser-only: provide an explicit Worker script URL.
     *
     * Useful under strict CSP that blocks `blob:` workers. When set, the browser
     * parser will try to construct `new Worker(workerInflateUrl)`.
     */
    workerInflateUrl?: string;
    /**
     * Input backpressure high-water mark (bytes).
     *
     * When provided, implementations may delay the writable callback until the
     * internal input buffer drops below `inputLowWaterMarkBytes`.
     *
     * This is primarily used by the browser parser, because its writable side
     * otherwise tends to accept unlimited data and can cause large memory spikes.
     */
    inputHighWaterMarkBytes?: number;
    /**
     * Input backpressure low-water mark (bytes).
     * When the internal buffer drops to (or below) this value, a delayed writable
     * callback may be released.
     */
    inputLowWaterMarkBytes?: number;
    /**
     * Threshold (in bytes) for small file optimization.
     * Files smaller than this will use sync decompression (no stream overhead).
     *
     * Note: the optimization is only applied when the entry sizes are trusted
     * (i.e. no data descriptor) and BOTH compressedSize and uncompressedSize
     * are below this threshold. This avoids buffering huge highly-compressible
     * files (e.g. large XML) in memory, which would defeat streaming.
     * Default: 5MB
     */
    thresholdBytes?: number;
}
export interface EntryVars {
    versionsNeededToExtract: number | null;
    flags: number | null;
    compressionMethod: number | null;
    lastModifiedTime: number | null;
    lastModifiedDate: number | null;
    crc32: number | null;
    compressedSize: number | null;
    uncompressedSize: number | null;
    fileNameLength: number | null;
    extraFieldLength: number | null;
    lastModifiedDateTime?: Date;
    crxHeader?: CrxHeader;
}
export interface EntryProps {
    path: string;
    pathBuffer: Uint8Array;
    flags: {
        isUnicode: boolean;
    };
}
export interface ZipEntry extends PassThrough {
    path: string;
    props: EntryProps;
    type: "Directory" | "File";
    vars: EntryVars;
    extraFields: ZipExtraFields;
    size?: number;
    __autodraining?: boolean;
    autodrain: () => DrainStream;
    buffer: () => Promise<Uint8Array>;
}
export interface ParseDriverState {
    crxHeader?: CrxHeader;
    reachedCD?: boolean;
}
export interface ParseIO {
    pull(length: number): Promise<Uint8Array>;
    pullUntil(pattern: Uint8Array, includeEof?: boolean): Promise<Uint8Array>;
    stream(length: number): PassThrough;
    streamUntilDataDescriptor(): PassThrough;
    setDone(): void;
}
export interface ParseEmitter {
    emitEntry(entry: ZipEntry): void;
    pushEntry(entry: ZipEntry): void;
    pushEntryIfPiped(entry: ZipEntry): void;
    emitCrxHeader(header: CrxHeader): void;
    emitError(err: Error): void;
    emitClose(): void;
}
export type InflateFactory = () => Transform | Duplex | PassThrough;
/**
 * Synchronous inflate function type for small file optimization.
 * When provided and file size is below threshold, this will be used
 * instead of streaming decompression for better performance.
 */
export type InflateRawSync = (data: Uint8Array) => Uint8Array;
/**
 * Default threshold for small file optimization (5MB).
 */
export declare const DEFAULT_PARSE_THRESHOLD_BYTES: number;
export declare function runParseLoop(opts: ParseOptions, io: ParseIO, emitter: ParseEmitter, inflateFactory: InflateFactory, state: ParseDriverState, inflateRawSync?: InflateRawSync): Promise<void>;
