/**
 * Represents a stream of input data, either as a string or binary data buffer.
 *
 * All input types are converted to an `Int8Array` byte buffer prior to being
 * processed by the decompression algorithm.
 */
export declare class InputStream {
  offset: number;
  data: Int8Array;
  constructor(data: BufferSource, offset?: number);
}

/**
 * The core of the Brotli decompression algorithm, implemented as a stateful
 * class that can be used to decompress multiple chunks of data in sequence.
 *
 * This is used internally by the {@linkcode decompress} function, but can also
 * be used directly to decompress data in a streaming fashion. It's a low-level
 * API that provides fine-grained control over the decompression process, so
 * it's not as user-friendly as the top-level function.
 */
export declare class State {
  #private;
  static readonly offsets: Int32Array;
  static readonly sizeBits: Int32Array;
  /**
   * Returns a boolean indicating whether or not the default dictionary has
   * been initialized. This is used to ensure that the dictionary is only
   * initialized once, and that it's not re-initialized if a custom dictionary
   * is provided.
   * @internal
   */
  static readonly initialized: boolean;
  /**
   * Returns the default dictionary data as a `Int8Array` buffer. This is the
   * data that is used to initialize the decompression state when no custom
   * dictionary is provided.
   * @internal
   */
  static readonly dictionaryData: Int8Array;
  /**
   * Updates the default dictionary data with new data and size bits, after
   * validating the input data to ensure that it's consistent with the size
   * bits and aligned correctly. This is used to set the default dictionary
   * data that is used when no custom dictionary is provided.
   *
   * @param newData The new dictionary data to use.
   * @param newSizeBits The size bits for the new dictionary data.
   * @throws {BrotliDecoderDictionaryError} If the new data is inconsistent.
   */
  static setDictionaryData(newData: Int8Array, newSizeBits: Int32Array): void;
  /**
   * Decompresses a Brotli-compressed input source (either from a string or a
   * `BufferSource` object), optionally using a custom dictionary, and returns
   * the decompressed data as a `Uint8Array` binary buffer.
   *
   * This is a convenience method for creating a new `State` instance, adding
   * the input data, configuring the custom dictionary (if necessary), and then
   * calling the `decompress` method on the instance.
   *
   * @param bytes The Brotli-compressed data to be decoded.
   * @param dict A custom dictionary to be used during decompression.
   * @returns The decompressed data, as a `Uint8Array` object.
   */
  static decompress(
    bytes: BufferSource,
    dict?: BufferSource | null,
  ): Uint8Array;
  static readonly RFC_TRANSFORMS: Transforms;
  /**
   * The input stream object that is being used to read the compressed data.
   * This can be useful for checking the current offset into the input data, or
   * for reading the input data directly. It can also be used to implement
   * custom streaming input sources.
   */
  readonly input: InputStream;
  /**
   * The total number of bytes that have been decompressed so far. When the
   * decompression job is complete, this value will represent the total length
   * of the decompressed data.
   */
  totalOutput: number;
  /** @internal */ outputUsed: number;
  /** @internal */ outputOffset: number;
  /** @internal */ outputLength: number;
  /** @internal */ expectedTotalSize: number;
  /** @internal */ runningState: number;
  /** @internal */ nextRunningState: number;
  /** @internal */ chunks: Int8Array[];
  /** @internal */ byteBuffer: Int8Array;
  /** @internal */ output: Int8Array;
  /** @internal */ ringBuffer: Int8Array;
  /** @internal */ contextModes: Int8Array;
  /** @internal */ contextMap: Int8Array;
  /** @internal */ distContextMap: Int8Array;
  /** @internal */ distExtraBits: Int8Array;
  /** @internal */ shortBuffer: Int16Array;
  /** @internal */ rings: Int32Array;
  /** @internal */ blockTrees: Int32Array;
  /** @internal */ commandTreeGroup: Int32Array;
  /** @internal */ distanceTreeGroup: Int32Array;
  /** @internal */ literalTreeGroup: Int32Array;
  /** @internal */ distOffset: Int32Array;
  /** @internal */ bitOffset: number;
  /** @internal */ halfOffset: number;
  /** @internal */ accumulator32: number;
  /** @internal */ tailBytes: number;
  /** @internal */ endOfStreamReached: number;
  /** @internal */ inputEnd: number;
  /** @internal */ isUncompressed: number;
  /** @internal */ isMetadata: number;
  /** @internal */ isEager: number;
  /** @internal */ isLargeWindow: number;
  /** @internal */ numLiteralBlockTypes: number;
  /** @internal */ numCommandBlockTypes: number;
  /** @internal */ numDistanceBlockTypes: number;
  /** @internal */ trivialLiteralContext: number;
  /** @internal */ literalTreeIdx: number;
  /** @internal */ commandTreeIdx: number;
  /** @internal */ pos: number;
  /** @internal */ j: number;
  /** @internal */ contextMapSlice: number;
  /** @internal */ contextLookupOffset1: number;
  /** @internal */ contextLookupOffset2: number;
  /** @internal */ numDirectDistanceCodes: number;
  /** @internal */ insertLength: number;
  /** @internal */ copyLength: number;
  /** @internal */ metaBlockLength: number;
  /** @internal */ commandBlockLength: number;
  /** @internal */ literalBlockLength: number;
  /** @internal */ distanceBlockLength: number;
  /** @internal */ distContextMapSlice: number;
  /** @internal */ distanceCode: number;
  /** @internal */ distancePostfixBits: number;
  /** @internal */ distance: number;
  /** @internal */ distRbIdx: number;
  /** @internal */ maxDistance: number;
  /** @internal */ maxBackwardDistance: number;
  /** @internal */ maxRingBufferSize: number;
  /** @internal */ ringBufferSize: number;
  /** @internal */ ringBufferBytesWritten: number;
  /** @internal */ ringBufferBytesReady: number;
  /** @internal */ cdNumChunks: number;
  /** @internal */ cdTotalSize: number;
  /** @internal */ cdBrIndex: number;
  /** @internal */ cdBrOffset: number;
  /** @internal */ cdBrLength: number;
  /** @internal */ cdBrCopied: number;
  /** @internal */ cdChunks: Int8Array[];
  /** @internal */ cdChunkOffsets: Int32Array;
  /** @internal */ cdBlockBits: number;
  /** @internal */ cdBlockMap: Int8Array;
  /**
   * Creates a new `State` instance, optionally with a custom dictionary, and
   * initializes the decompression job. The input data can be provided as a
   * string or a `BufferSource` object, and the dictionary can be provided as
   * a string, `BufferSource`, or `null` to use the default dictionary.
   *
   * This is the core of the Brotli decompression algorithm.
   */
  constructor(bytes?: BufferSource, dict?: BufferSource | null);
  /**
   * Decompresses a Brotli-compressed input source (either from a string or a
   * `BufferSource` object), optionally using a custom dictionary, and returns
   * the decompressed data as a `Uint8Array` binary buffer.
   */
  decompress(): Uint8Array;
  /**
   * Reads input data from the internal {@linkcode InputStream} into a given
   * `Int8Array` byte buffer, reading from `offset` up to the given `length`.
   * Used internally to consume the input stream during decompression.
   *
   * @param data The input buffer to read into.
   * @param offset The offset within the input buffer to start reading from.
   * @param length The maximum number of bytes to read from the input buffer.
   * @returns The number of bytes that were read from the input buffer.
   */
  readInput(data: Int8Array, offset: number, length: number): number;
  protected init(): this;
  protected initBitReader(): this;
  protected close(): void;
  protected prepare(): this;
  protected reload(): this;
  protected attachDictionaryChunk(buf: string | BufferSource): void;
  protected initializeCompoundDictionary(): void;
  protected initializeCompoundDictionaryCopy(
    address: number,
    length: number,
  ): void;
  protected copyFromCompoundDictionary(fence: number): number;
  protected copyRawBytes(data: Int8Array, offset: number, length: number): void;
  protected copyUncompressedData(): void;
  protected bytesToNibbles(byteLen: number): void;
  protected calculateDistanceLut(alphabetSizeLimit: number): void;
  protected calculateFence(): number;
  protected decompressChunk(): void;
  protected doReadMoreInput(): void;
  protected doUseDictionary(fence: number): void;
  protected checkHealth(endOfStream: number): void;
  protected readFewBits(n: number): number;
  protected readManyBits(n: number): number;
  protected jumpToByteBoundary(): void;
  protected halfAvailable(): number;
  protected decodeWindowBits(): number;
  protected decodeVarLenUnsignedByte(): number;
  protected decodeMetaBlockLength(): void;
  protected decodeLiteralBlockSwitch(): void;
  protected decodeContextMap(
    contextMapSize: number,
    contextMap: Int8Array,
  ): number;
  protected decodeBlockTypeAndLength(
    treeType: number,
    numBlockTypes: number,
  ): number;
  protected decodeHuffmanTreeGroup(
    alphabetSizeMax: number,
    alphabetSizeLimit: number,
    n: number,
  ): Int32Array;
  protected moveToFront(v: Int32Array, index: number): void;
  protected inverseMoveToFrontTransform(v: Int8Array, vLen: number): void;
  protected maybeReallocateRingBuffer(): void;
  protected readHuffmanCodeLengths(
    codeLengthCodeLengths: Int32Array,
    numSymbols: number,
    codeLengths: Int32Array,
  ): void;
  protected readNextMetablockHeader(): void;
  protected readMetablockPartition(
    treeType: number,
    numBlockTypes: number,
  ): number;
  protected readSimpleHuffmanCode(
    alphabetSizeMax: number,
    alphabetSizeLimit: number,
    tableGroup: Int32Array,
    tableIdx: number,
  ): number;
  protected readComplexHuffmanCode(
    alphabetSizeLimit: number,
    skip: number,
    tableGroup: Int32Array,
    tableIdx: number,
  ): number;
  protected readHuffmanCode(
    alphabetSizeMax: number,
    alphabetSizeLimit: number,
    tableGroup: Int32Array,
    tableIdx: number,
  ): number;
  protected readSymbol(tableGroup: Int32Array, tableIdx: number): number;
  protected readBlockLength(tableGroup: Int32Array, tableIdx: number): number;
  protected calculateDistanceAlphabetLimit(
    maxDistance: number,
    npostfix: number,
    ndirect: number,
  ): number;
  protected readMetablockHuffmanCodesAndContextMaps(): void;
  protected checkDupes(symbols: Int32Array, length: number): void;
  protected writeRingBuffer(): number;
}

export declare class Transforms {
  readonly numTransforms: number;
  readonly prefixSuffixLen: number;
  readonly prefixSuffixCount: number;
  readonly triplets: Int32Array;
  readonly prefixSuffixStorage: Int8Array;
  readonly prefixSuffixHeads: Int32Array;
  readonly params: Int16Array;

  constructor(
    numTransforms: number,
    prefixSuffixLen: number,
    prefixSuffixCount: number,
  );

  unpack(prefixSuffixSrc: string, transformsSrc: string): this;
  transformDictionaryWord(
    dst: Int8Array,
    dstOffset: number,
    src: Int8Array,
    srcOffset: number,
    wordLen: number,
    transformIndex: number,
  ): number;
}

/**
 * Represents the result codes that can be returned by the Brotli decoder.
 *
 * @category Errors
 */
export declare const enum BrotliDecoderResult {
  ERROR = 0,
  SUCCESS = 1,
  NEEDS_MORE_INPUT = 2,
  NEEDS_MORE_OUTPUT = 3,
}
/**
 * Represents the error codes that can be returned by the Brotli decoder.
 *
 * @category Errors
 */
export declare const enum BrotliErrorCode {
  UNKNOWN = -32,
  UNREACHABLE = -31,
  ALLOC_BLOCK_TYPE_TREES = -30,
  ALLOC_RING_BUFFER_2 = -27,
  ALLOC_RING_BUFFER_1 = -26,
  ALLOC_CONTEXT_MAP = -25,
  ALLOC_TREE_GROUPS = -22,
  ALLOC_CONTEXT_MODES = -21,
  INVALID_ARGUMENTS = -20,
  DICTIONARY_NOT_SET = -19,
  FORMAT_DISTANCE = -16,
  FORMAT_PADDING_2 = -15,
  FORMAT_PADDING_1 = -14,
  FORMAT_WINDOW_BITS = -13,
  FORMAT_DICTIONARY = -12,
  FORMAT_TRANSFORM = -11,
  FORMAT_BLOCK_LENGTH_2 = -10,
  FORMAT_BLOCK_LENGTH_1 = -9,
  FORMAT_CONTEXT_MAP_REPEAT = -8,
  FORMAT_HUFFMAN_SPACE = -7,
  FORMAT_CL_SPACE = -6,
  FORMAT_SIMPLE_HUFFMAN_SAME = -5,
  FORMAT_SIMPLE_HUFFMAN_ALPHABET = -4,
  FORMAT_EXUBERANT_META_NIBBLE = -3,
  FORMAT_RESERVED = -2,
  FORMAT_EXUBERANT_NIBBLE = -1,
  NO_ERROR = 0,
  SUCCESS = 1,
  NEEDS_MORE_INPUT = 2,
  NEEDS_MORE_OUTPUT = 3,
}

/**
 * Represents a Brotli decoder error.
 * @category Errors
 */
type BROTLI_ERROR_NAMES = keyof {
  [
    K in keyof typeof BrotliErrorCode as K extends `${number}` | number ? never
      : K
  ]: K;
};

export interface BrotliErrorOptions<
  K extends BROTLI_ERROR_NAMES = BROTLI_ERROR_NAMES,
> extends ErrorOptions {
  code?: typeof BrotliErrorCode[K] | undefined;
  name?: K | undefined;
  message?: string | undefined;
  cause?: string | Error;
}

export interface BrotliErrorJson<K extends BROTLI_ERROR_NAMES> {
  code: typeof BrotliErrorCode[K];
  name: K;
  message: string;
  cause?: string | Error | undefined;
}

declare abstract class BrotliError<K extends BROTLI_ERROR_NAMES> extends Error {
  abstract readonly code: typeof BrotliErrorCode[K];

  readonly name: K;
  readonly message: string;
  readonly options: BrotliErrorOptions<K>;
  readonly cause: string | Error | undefined;

  constructor(message?: string, options?: BrotliErrorOptions<K>);

  toJSON(): BrotliErrorJson<K>;

  static from<K extends BROTLI_ERROR_NAMES>(
    json: BrotliErrorJson<K>,
  ): Extract<AnyBrotliError, { readonly name: K }>;
}

declare type AnyBrotliError =
  | BrotliDecoderUnknownError
  | BrotliDecoderUnreachableError
  | BrotliDecoderAllocBlockTypeTreesError
  | BrotliDecoderAllocRingBuffer2Error
  | BrotliDecoderAllocRingBuffer1Error
  | BrotliDecoderAllocContextMapError
  | BrotliDecoderAllocTreeGroupsError
  | BrotliDecoderAllocContextModesError
  | BrotliDecoderInvalidArgumentsError
  | BrotliDecoderDictionaryNotSetError
  | BrotliDecoderDistanceError
  | BrotliDecoderPadding2Error
  | BrotliDecoderPadding1Error
  | BrotliDecoderWindowBitsError
  | BrotliDecoderDictionaryError
  | BrotliDecoderTransformError
  | BrotliDecoderBlockLength2Error
  | BrotliDecoderBlockLength1Error
  | BrotliDecoderContextMapRepeatError
  | BrotliDecoderHuffmanSpaceError
  | BrotliDecoderClSpaceError
  | BrotliDecoderSimpleHuffmanSameError
  | BrotliDecoderSimpleHuffmanAlphabetError
  | BrotliDecoderExuberantMetaNibbleError
  | BrotliDecoderReservedError
  | BrotliDecoderExuberantNibbleError
  | BrotliDecoderNoErrorResult
  | BrotliDecoderSuccessResult
  | BrotliDecoderNeedsMoreInputResult
  | BrotliDecoderNeedsMoreOutputResult;

export declare class BrotliDecoderUnknownError extends BrotliError<"UNKNOWN"> {
  readonly code: BrotliErrorCode.UNKNOWN;
}

export declare class BrotliDecoderUnreachableError
  extends BrotliError<"UNREACHABLE"> {
  readonly code: BrotliErrorCode.UNREACHABLE;
}

export declare class BrotliDecoderAllocBlockTypeTreesError
  extends BrotliError<"ALLOC_BLOCK_TYPE_TREES"> {
  readonly code: BrotliErrorCode.ALLOC_BLOCK_TYPE_TREES;
}

export declare class BrotliDecoderAllocRingBuffer2Error
  extends BrotliError<"ALLOC_RING_BUFFER_2"> {
  readonly code: BrotliErrorCode.ALLOC_RING_BUFFER_2;
}

export declare class BrotliDecoderAllocRingBuffer1Error
  extends BrotliError<"ALLOC_RING_BUFFER_1"> {
  readonly code: BrotliErrorCode.ALLOC_RING_BUFFER_1;
}

export declare class BrotliDecoderAllocContextMapError
  extends BrotliError<"ALLOC_CONTEXT_MAP"> {
  readonly code: BrotliErrorCode.ALLOC_CONTEXT_MAP;
}

export declare class BrotliDecoderAllocTreeGroupsError
  extends BrotliError<"ALLOC_TREE_GROUPS"> {
  readonly code: BrotliErrorCode.ALLOC_TREE_GROUPS;
}

export declare class BrotliDecoderAllocContextModesError
  extends BrotliError<"ALLOC_CONTEXT_MODES"> {
  readonly code: BrotliErrorCode.ALLOC_CONTEXT_MODES;
}

export declare class BrotliDecoderInvalidArgumentsError
  extends BrotliError<"INVALID_ARGUMENTS"> {
  readonly code: BrotliErrorCode.INVALID_ARGUMENTS;
}

export declare class BrotliDecoderDictionaryNotSetError
  extends BrotliError<"DICTIONARY_NOT_SET"> {
  readonly code: BrotliErrorCode.DICTIONARY_NOT_SET;
}

export declare class BrotliDecoderDistanceError
  extends BrotliError<"FORMAT_DISTANCE"> {
  readonly code: BrotliErrorCode.FORMAT_DISTANCE;
}

export declare class BrotliDecoderPadding2Error
  extends BrotliError<"FORMAT_PADDING_2"> {
  readonly code: BrotliErrorCode.FORMAT_PADDING_2;
}

export declare class BrotliDecoderPadding1Error
  extends BrotliError<"FORMAT_PADDING_1"> {
  readonly code: BrotliErrorCode.FORMAT_PADDING_1;
}

export declare class BrotliDecoderWindowBitsError
  extends BrotliError<"FORMAT_WINDOW_BITS"> {
  readonly code: BrotliErrorCode.FORMAT_WINDOW_BITS;
}

export declare class BrotliDecoderDictionaryError
  extends BrotliError<"FORMAT_DICTIONARY"> {
  readonly code: BrotliErrorCode.FORMAT_DICTIONARY;
}

export declare class BrotliDecoderTransformError
  extends BrotliError<"FORMAT_TRANSFORM"> {
  readonly code: BrotliErrorCode.FORMAT_TRANSFORM;
}

export declare class BrotliDecoderBlockLength2Error
  extends BrotliError<"FORMAT_BLOCK_LENGTH_2"> {
  readonly code: BrotliErrorCode.FORMAT_BLOCK_LENGTH_2;
}

export declare class BrotliDecoderBlockLength1Error
  extends BrotliError<"FORMAT_BLOCK_LENGTH_1"> {
  readonly code: BrotliErrorCode.FORMAT_BLOCK_LENGTH_1;
}

export declare class BrotliDecoderContextMapRepeatError
  extends BrotliError<"FORMAT_CONTEXT_MAP_REPEAT"> {
  readonly code: BrotliErrorCode.FORMAT_CONTEXT_MAP_REPEAT;
}

export declare class BrotliDecoderHuffmanSpaceError
  extends BrotliError<"FORMAT_HUFFMAN_SPACE"> {
  readonly code: BrotliErrorCode.FORMAT_HUFFMAN_SPACE;
}

export declare class BrotliDecoderClSpaceError
  extends BrotliError<"FORMAT_CL_SPACE"> {
  readonly code: BrotliErrorCode.FORMAT_CL_SPACE;
}

export declare class BrotliDecoderSimpleHuffmanSameError
  extends BrotliError<"FORMAT_SIMPLE_HUFFMAN_SAME"> {
  readonly code: BrotliErrorCode.FORMAT_SIMPLE_HUFFMAN_SAME;
}

export declare class BrotliDecoderSimpleHuffmanAlphabetError
  extends BrotliError<"FORMAT_SIMPLE_HUFFMAN_ALPHABET"> {
  readonly code: BrotliErrorCode.FORMAT_SIMPLE_HUFFMAN_ALPHABET;
}

export declare class BrotliDecoderExuberantMetaNibbleError
  extends BrotliError<"FORMAT_EXUBERANT_META_NIBBLE"> {
  readonly code: BrotliErrorCode.FORMAT_EXUBERANT_META_NIBBLE;
}

export declare class BrotliDecoderReservedError
  extends BrotliError<"FORMAT_RESERVED"> {
  readonly code: BrotliErrorCode.FORMAT_RESERVED;
}

export declare class BrotliDecoderExuberantNibbleError
  extends BrotliError<"FORMAT_EXUBERANT_NIBBLE"> {
  readonly code: BrotliErrorCode.FORMAT_EXUBERANT_NIBBLE;
}

export declare class BrotliDecoderNoErrorResult
  extends BrotliError<"NO_ERROR"> {
  readonly code: BrotliErrorCode.NO_ERROR;
}

export declare class BrotliDecoderSuccessResult extends BrotliError<"SUCCESS"> {
  readonly code: BrotliErrorCode.SUCCESS;
}

export declare class BrotliDecoderNeedsMoreInputResult
  extends BrotliError<"NEEDS_MORE_INPUT"> {
  readonly code: BrotliErrorCode.NEEDS_MORE_INPUT;
}

export declare class BrotliDecoderNeedsMoreOutputResult
  extends BrotliError<"NEEDS_MORE_OUTPUT"> {
  readonly code: BrotliErrorCode.NEEDS_MORE_OUTPUT;
}

/**
 * Options for the {@linkcode decompress} function, to customize the behavior
 * of the Brotli decompression process. Currently the only supported option is
 * a custom dictionary for the decompressor to use.
 *
 * @category Options
 */
export interface BrotliDecodeOptions {
  /**
   * Custom dictionary to use for the Brotli decompression process. This should
   * be a BufferSource object containing text-based dictionary data, or `null`
   * to use the default dictionary.
   *
   * @remarks
   * The dictionary must be a valid Brotli dictionary, and must be the same
   * dictionary that was used to compress the data. If the dictionary is not
   * valid, or if it does not match the dictionary used to compress the data,
   * the decompression process will almost certainly fail.
   */
  customDictionary: BufferSource | null;
}

/**
 * Decodes a `BufferSource` object containing Brotli-compressed data, returning
 * the decompressed output as a new `Uint8Array` object.
 *
 * @param input The Brotli-compressed data to be decoded.
 * @param [options] Custom decompression options (if any), allowing you to pass
 * in a custom dictionary to the decoder. See {@linkcode BrotliDecodeOptions}
 * for details on custom dictionary requirements and usage.
 * @returns The decompressed data in a new `Uint8Array` buffer.
 * @example Decompressing a Brotli-compressed file:
 * ```ts no-eval
 * import { decompress } from "brocha";
 * import { readFileSync } from "node:fs";
 *
 * const compressed = readFileSync("data.wasm.br");
 * const decompressed = decompress(compressed);
 *
 * const input = +(compressed.byteLength / 1024).toFixed(0);
 * const output = +(decompressed.byteLength / 1024).toFixed(0);
 * const delta = (
 *
 * console.log(`${input}K => ${output}K (${delta > 0 ? "+" : ""}${delta}%)`);
 * // Example log: "115K => 483K (+4.2x)"
 * ```
 * @example Instantiating a brotli-compressed WebAssembly module:
 * ```ts no-eval
 * import { decompress } from "brocha";
 * import { add, instantiate } from "./add.generated.js";
 *
 * await instantiate({ decompress });
 * console.log(add(1, 2)); // 3
 * ```
 */
export declare function decompress(
  input: BufferSource,
  options?: BrotliDecodeOptions,
): Uint8Array;

export default decompress;
