export interface BinpatOption {
    /** The global endianness. Default value is `big`. */
    endian: 'big' | 'little';
}
export interface BinpatContext {
    endian: BinpatOption['endian'];
    parent?: BinpatContext;
    offset: number;
    data: Record<string, any>;
}
type BinpatHandler<T> = (dv: DataView, ctx: BinpatContext) => T;
type BinpatPattern = BinpatHandler<any> | BinpatPatternObject | BinpatPattern[] | string | number | boolean;
interface BinpatPatternObject {
    [key: string]: BinpatPattern;
}
type Merge<T, U> = Omit<T, keyof U> & U;
type RegularProps<P extends BinpatPatternObject> = {
    [K in keyof P as K extends `//${string}` | `...${string}` ? never : K]: InferOutput<P[K]>;
};
type SpreadSourceType<P extends BinpatPatternObject> = {
    [K in keyof P as K extends `...${string}` ? K : never]: InferOutput<P[K]>;
} extends infer SpreadEntries ? keyof SpreadEntries extends never ? unknown : SpreadEntries[keyof SpreadEntries] : never;
type Prettify<T> = {
    [K in keyof T]: T[K];
} & {};
type InferOutput<P> = P extends BinpatHandler<infer T> ? T : P extends (infer ElementPattern)[] ? {
    [I in keyof P]: InferOutput<P[I]>;
} : P extends BinpatPatternObject ? (SpreadSourceType<P> extends infer S ? unknown extends S ? Prettify<RegularProps<P>> : S extends infer S_Item ? Prettify<Merge<S_Item, RegularProps<P>>> : never : never) : P extends string | number | boolean | bigint | null | undefined ? P : unknown;
declare const BINPAT_ARRAY: unique symbol;
/**
 * Parse binary data using declarative patterns.
 *
 * @example Usage
 * ```js
 * import Binpat, { u8 } from 'binpat';
 * const binpat = new Binpat({ foo: u8() });
 * ```
 */
export default class Binpat<P extends BinpatPattern> {
    #private;
    endian: BinpatOption['endian'];
    /** Create a new Binpat instance. */
    constructor(pattern: P, option?: BinpatOption);
    /**
     * Executes the pattern against the buffer.
     * @param buffer The ArrayBuffer containing the binary data.
     *
     * @example Usage
     * ```js
     * import { assertEquals } from '@std/assert';
     * import Binpat, { u8 } from 'binpat';
     *
     * const binpat = new Binpat({ foo: u8() });
     * const { buffer } = new Uint8Array([1]);
     * assertEquals(binpat.exec(buffer), { foo: 1 });
     * ```
     */
    exec(buffer: ArrayBuffer): InferOutput<P>;
}
type TypedArrayConstructor = Uint8ArrayConstructor | Uint16ArrayConstructor | Uint32ArrayConstructor | BigUint64ArrayConstructor | Int8ArrayConstructor | Int16ArrayConstructor | Int32ArrayConstructor | BigInt64ArrayConstructor | Float16ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor;
type GetElementType<C> = C extends new () => infer T ? T extends {
    [n: number]: infer E;
} ? E : never : never;
type BinpatTypedHandler<C extends TypedArrayConstructor> = BinpatHandler<GetElementType<C>> & {
    [BINPAT_ARRAY]: C;
};
type GenTypedHandler<C extends TypedArrayConstructor> = (
/**
 * Indicates whether the data is stored in little- or big-endian format.
 * If not specified, the global endianness is used.
 */
littleEndian?: boolean) => BinpatTypedHandler<C>;
/** Reads 1 byte and interprets it as an 8-bit unsigned integer. */
export declare const u8: () => BinpatTypedHandler<Uint8ArrayConstructor>;
/** Reads 2 bytes and interprets them as a 16-bit unsigned integer. */
export declare const u16: GenTypedHandler<Uint16ArrayConstructor>;
/** Reads 4 bytes and interprets them as a 32-bit unsigned integer. */
export declare const u32: GenTypedHandler<Uint32ArrayConstructor>;
/** Reads 8 bytes and interprets them as a 64-bit unsigned integer. */
export declare const u64: GenTypedHandler<BigUint64ArrayConstructor>;
/** Reads 1 byte and interprets it as an 8-bit signed integer. */
export declare const i8: () => BinpatTypedHandler<Int8ArrayConstructor>;
/** Reads 2 bytes and interprets them as a 16-bit signed integer. */
export declare const i16: GenTypedHandler<Int16ArrayConstructor>;
/** Reads 4 bytes and interprets them as a 32-bit signed integer. */
export declare const i32: GenTypedHandler<Int32ArrayConstructor>;
/** Reads 8 bytes and interprets them as a 64-bit signed integer. */
export declare const i64: GenTypedHandler<BigInt64ArrayConstructor>;
/** Reads 2 bytes and interprets them as a 16-bit floating point number. */
export declare const f16: GenTypedHandler<Float16ArrayConstructor>;
/** Reads 4 bytes and interprets them as a 32-bit floating point number. */
export declare const f32: GenTypedHandler<Float32ArrayConstructor>;
/** Reads 8 bytes and interprets them as a 64-bit floating point number. */
export declare const f64: GenTypedHandler<Float64ArrayConstructor>;
/** Reads 1 byte and and interprets it as a boolean value. */
export declare function bool(): BinpatHandler<boolean>;
/**
 * Reads the given number of bytes and decodes to a string.
 * @param size number of bytes
 * @param encoding same as [TextDecoder.encoding](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/encoding)
 *
 * @example Usage
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { string } from 'binpat';
 *
 * const binpat = new Binpat({ name: string(6) });
 * const { buffer } = new Uint8Array([98, 105, 110, 112, 97, 116]);
 * assertEquals(binpat.exec(buffer), { name: 'binpat' });
 * ```
 */
export declare function string(size: number | ((ctx: BinpatContext) => number), encoding?: TextDecoderCommon['encoding']): BinpatHandler<string>;
/**
 * Reads an array of values, all conforming to the same pattern.
 * If the pattern is a primitive type (like u8, u16),
 * it will return a TypedArray instance (e.g., Uint8Array).
 * Otherwise, it returns a regular array.
 * @param pattern The pattern definition for each element in the array.
 * @param size The number of elements to read, or a function returning the number based on context.
 *
 * @example Usage
 * ```js
 * import Binpat, { array, u16, u32, u8 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   // It will return Uint16Array
 *   foo: array(u16(), 4),
 *   // pattern can be object
 *   bar: array({ x: u8(), y: u8() }, 4),
 *   count: u32(),
 *   // get size from context
 *   baz: array(u8(), (ctx) => ctx.data.count),
 * });
 * ```
 */
export declare function array<P extends BinpatPattern>(pattern: P, size: number | ((ctx: BinpatContext) => number)): BinpatHandler<P extends {
    [BINPAT_ARRAY]: infer TC;
} ? TC extends TypedArrayConstructor ? InstanceType<TC> : InferOutput<P>[] : InferOutput<P>[]>;
type BitfieldTypeUnsigned = {
    type: 'u';
    size: number;
};
type BitfieldTypeSigned = {
    type: 'i';
    size: number;
};
type BitfieldTypeBoolean = {
    type: 'bool';
    size: 1;
};
type BitfieldType = BitfieldTypeUnsigned | BitfieldTypeSigned | BitfieldTypeBoolean;
type BitfieldLayout = {
    [name: string]: number | BitfieldType;
};
type BitfieldOption = {
    /**
     * The endianness of the bitfield. If not specified, it will use the global endianness.
     */
    endian?: BinpatOption['endian'];
    /**
     * Which bit comes first, see [Bit numbering](https://en.wikipedia.org/wiki/Bit_numbering).
     * + 'MSb': Most Significant Bit (left-to-right).
     * + 'LSb': Least Significant Bit (right-to-left).
     *
     * If not specified:
     * + When endian is `big`, the first bit is `MSb`.
     * + When endian is `little`, the first bit is `LSb`.
     */
    first?: 'MSb' | 'LSb';
};
type InferBitResult<Def extends number | BitfieldType> = Def extends BitfieldTypeBoolean ? boolean : number;
type InferBitfieldOutput<F extends BitfieldLayout> = Prettify<{
    [K in keyof F as K extends `//${string}` ? never : K]: InferBitResult<F[K] extends number ? {
        type: 'u';
        size: F[K];
    } : F[K]>;
}>;
/**
 * Reads a bitfield.
 *
 * @example Usage
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { bitfield, omit } from 'binpat';
 *
 * const binpat = new Binpat(bitfield({
 *   a: 3, // unsigned, 3 bits
 *   b: bitfield.u(3), // unsigned, 3 bits
 *   [omit('padding')]: 4, // padding, 4 bits
 *   c: bitfield.i(5), // signed, 5 bits
 *   d: bitfield.bool(), // boolean, 1 bit
 * }));
 * const { buffer } = new Uint8Array([0b01010101, 0b11001100]);
 * assertEquals(binpat.exec(buffer), {
 *   a: 2,     // 0b010
 *   b: 5,     // 0b101
 *             // 0b0111 (padding)
 *   c: 6,     // 0b00110
 *   d: false, // 0b0
 * });
 * ```
 */
export declare function bitfield<Layout extends BitfieldLayout>(field: Layout, option?: BitfieldOption): BinpatHandler<InferBitfieldOutput<Layout>>;
export declare namespace bitfield {
    var u: (size: number) => BitfieldTypeUnsigned;
    var i: (size: number) => BitfieldTypeSigned;
    var bool: () => BitfieldTypeBoolean;
}
/**
 * It works like `condition(ctx) ? truthy : falsy`
 * @param condition
 * @param truthy
 * @param falsy
 *
 * @example Usage
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { ternary, bool, u16, u8 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   flag: bool(),
 *   value: ternary((ctx) => ctx.data.flag, [u8(), u8()], [u16()]),
 * });
 * assertEquals(binpat.exec(new Uint8Array([1, 0, 0]).buffer), { flag: true, value: [0, 0] });
 * assertEquals(binpat.exec(new Uint8Array([0, 0, 0]).buffer), { flag: false, value: [0] });
 * ```
 */
export declare function ternary<T extends BinpatPattern, F extends BinpatPattern>(condition: (ctx: BinpatContext) => boolean, truthy: T, falsy?: F): BinpatHandler<InferOutput<T> | (undefined extends F ? undefined : InferOutput<F>)>;
/**
 * Convert the result value with custom function.
 * @param pattern
 * @param fn
 *
 * @example Usage
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { convert, u16 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   type: convert(u16(), (value) => ['', 'ico', 'cur'][value] || 'unknown'),
 * });
 * assertEquals(binpat.exec(new Uint8Array([0, 1]).buffer), { type: 'ico' });
 * assertEquals(binpat.exec(new Uint8Array([0, 2]).buffer), { type: 'cur' });
 * assertEquals(binpat.exec(new Uint8Array([0, 0]).buffer), { type: 'unknown' });
 * ```
 */
export declare function convert<P extends BinpatPattern, R>(pattern: P, fn: (value: InferOutput<P>, ctx?: BinpatContext) => R): BinpatHandler<R>;
/**
 * Move current offset to the given offset.
 * @param offset
 *
 * @example Usage
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { seek, omit, u8 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   foo: u8(),
 *   [omit('padding')]: seek((ctx) => ctx.offset + 4),
 *   bar: u8(),
 * });
 * const { buffer } = new Uint8Array([1, 0, 0, 0, 0, 2]);
 * assertEquals(binpat.exec(buffer), { foo: 1, bar: 2 });
 * ```
 */
export declare function seek(offset: number | ((ctx: BinpatContext) => number)): BinpatHandler<void>;
/**
 * Reads pattern from the given offset, and doesn't move current offset.
 * @param offset
 * @param pattern
 *
 * @example Usage
 * ```js
 * import Binpat, { peek, u8 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   size: u32(),
 *   address: u32(),
 *   data: peek(
 *     (ctx) => ctx.data.address,
 *     array(u8(), (ctx) => ctx.data.size),
 *   ),
 * });
 * ```
 */
export declare function peek<P extends BinpatPattern>(offset: number | ((ctx: BinpatContext) => number), pattern: P): BinpatHandler<InferOutput<P>>;
/**
 * Move forward with the given offset. `skip(x)` is same as `seek((ctx) => ctx.offset + x)`
 * @param offset
 *
 * @example Usage
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { skip, omit, u8 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   foo: u8(),
 *   [omit('padding')]: skip(4),
 *   bar: u8(),
 * });
 * const { buffer } = new Uint8Array([1, 0, 0, 0, 0, 2]);
 * assertEquals(binpat.exec(buffer), { foo: 1, bar: 2 });
 * ```
 */
export declare function skip(offset: number): BinpatHandler<void>;
/**
 * Omit the key-value in result.
 *
 * @example Usage
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { omit, u16 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   [omit('reserved')]: u16(),
 *   type: u16(),
 *   count: u16(),
 * });
 * const { buffer } = new Uint8Array([0, 0, 0, 1, 0, 1]);
 * assertEquals(binpat.exec(buffer), { type: 1, count: 1 });
 * ```
 *
 * @example Use string literal starts with `//` as object key to get correct type inference
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { omit, u16 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   '// reserved': u16(),
 *   type: u16(),
 *   count: u16(),
 * });
 * const { buffer } = new Uint8Array([0, 0, 0, 1, 0, 1]);
 * assertEquals(binpat.exec(buffer), { type: 1, count: 1 });
 */
export declare function omit(comment?: unknown): `//${string}`;
/**
 * It works like spread syntax `...`, and usually be used with `ternary()`.
 *
 * @example Usage
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { spread, ternary, bool, u8 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   flag: bool(),
 *   [spread()]: ternary(
 *     (ctx) => ctx.data.flag,
 *     { truthy: u8() },
 *     { falsy: u8() },
 *   ),
 * });
 * assertEquals(binpat.exec(new Uint8Array([1, 0]).buffer), { flag: true, truthy: 0 });
 * assertEquals(binpat.exec(new Uint8Array([0, 0]).buffer), { flag: false, falsy: 0 });
 * ```
 *
 * @example Use string literal starts with `...` as object key to get correct type inference
 * ```js
 * import { assertEquals } from '@std/assert';
 * import Binpat, { spread, ternary, bool, u8 } from 'binpat';
 *
 * const binpat = new Binpat({
 *   flag: bool(),
 *   '...spread': ternary(
 *     (ctx) => ctx.data.flag,
 *     { truthy: u8() },
 *     { falsy: u8() },
 *   ),
 * });
 * assertEquals(binpat.exec(new Uint8Array([1, 0]).buffer), { flag: true, truthy: 0 });
 * assertEquals(binpat.exec(new Uint8Array([0, 0]).buffer), { flag: false, falsy: 0 });
 * ```
 */
export declare function spread(comment?: unknown): `...${string}`;
export {};
