declare class Reader {
    private buffer;
    private offset;
    private view;
    constructor(buffer: Uint8Array, offset?: number);
    get position(): number;
    get remaining(): number;
    get bytes(): Uint8Array;
    private ensureBytes;
    readByte(): number;
    readBytes(count: number): Uint8Array;
    skipBytes(count: number): number;
    readUint16(littleEndian: boolean): number;
    readUint24(littleEndian: boolean): number;
    readUint32(littleEndian: boolean): number;
    readUint40(littleEndian: boolean): number;
    readUint48(littleEndian: boolean): number;
    readFloat32(littleEndian: boolean): number;
    readFloat64(littleEndian: boolean): number;
    readBigUint64(littleEndian: boolean): bigint;
    peekBytes(start: number, end: number): Uint8Array;
}

declare class Writer {
    private buffer;
    private view;
    private offset;
    constructor(buffer?: Uint8Array, initialSize?: number);
    get position(): number;
    get bytes(): Uint8Array;
    private ensureCapacity;
    toBuffer(): Uint8Array;
    reset(): void;
    writeByte(value: number): void;
    writeBytes(bytes: Uint8Array): void;
    reserve(byteLength: number): number;
    writeUint16(value: number, littleEndian: boolean): void;
    writeUint24(value: number, littleEndian: boolean): void;
    writeUint32(value: number, littleEndian: boolean): void;
    writeUint40(value: number, littleEndian: boolean): void;
    writeUint48(value: number, littleEndian: boolean): void;
    writeFloat32(value: number, littleEndian: boolean): void;
    writeFloat64(value: number, littleEndian: boolean): void;
    writeBigUint64(value: bigint, littleEndian: boolean): void;
}

type CodecType<T extends AbstractCodec<any>> = T extends AbstractCodec<infer S> ? S : never;
declare abstract class AbstractCodec<Value = unknown> {
    /**
     * Returns true if the provided value is able to be encoded and decoded by this codec.
     *
     * @param	{Value} value - Value of this codec's type.
     * @return	{boolean}
     *
     */
    abstract isValid(value: unknown): value is Value;
    /**
     * Returns the expected byteLength of the buffer if this value was encoded.
     *
     * @param	{Value} value - Value of this codec's type.
     * @return	{number} byteLength of buffer
     *
     */
    abstract byteLength(value: Value): number;
    /**
     * Used internally to recursively encode.
     *
     * @param	{Value} value - Value of this codec's type.
     * @param	{Writer} writer - Writer to encode into.
     * @return	{void}
     *
     */
    abstract _encode(value: Value, writer: Writer): void;
    /**
     * Encodes a value of this codecs type into a buffer.
     *
     * **Note:** This method does NOT validate the value before encoding.
     * Call `isValid()` first if you need to verify the value is encodable.
     * Encoding invalid values may result in undefined behavior or runtime errors.
     *
     * @param	{Value} value - Value of this codec's type.
     * @param	{Uint8Array} [target] - A target buffer to write into (uses byteLength for sizing).
     * @param	{number} [offset=0] - Offset at which to write into the target.
     * @return	{Uint8Array} Buffer encoding of value.
     *
     */
    encode(value: Value, target?: Uint8Array, offset?: number): Uint8Array;
    Encoder(): TransformStream<Value, Uint8Array>;
    /**
     * Used internally to recursively decode
     *
     * @param	{Reader} reader - Reader to decode from.
     * @return	{Value} Value decoded from the buffer
     *
     */
    abstract _decode(reader: Reader): Value;
    /**
     * Decodes a buffer to a value of this codecs type.
     *
     * @param	{Uint8Array} buffer - The buffer to be decoded.
     * @param	{number} [offset=0] - Offset at which to read at.
     * @return	{Value} Value decoded from the buffer
     *
     */
    decode(source: Uint8Array, offset?: number): Value;
    Decoder(): TransformStream<Uint8Array, Value>;
}

interface AnyCodecOptions<Value = any> {
    encode?: (value: Value) => Uint8Array;
    decode?: (buffer: Uint8Array) => Value;
    lengthCodec?: AbstractCodec<number>;
}
declare class AnyCodec<Value = any> extends AbstractCodec<Value> {
    private readonly _encodeValue;
    private readonly _decodeValue;
    readonly lengthCodec: AbstractCodec<number>;
    private readonly _bytesCodec;
    constructor(options?: AnyCodecOptions<Value>);
    isValid(_value: unknown): _value is any;
    byteLength(value: Value): number;
    _encode(value: Value, writer: Writer): void;
    _decode(reader: Reader): Value;
}

declare class ArrayFixedCodec<Item> extends AbstractCodec<Array<Item>> {
    readonly length: number;
    readonly itemCodec: AbstractCodec<Item>;
    constructor(length: number, itemCodec: AbstractCodec<Item>);
    isValid(value: unknown): value is Array<Item>;
    byteLength(value: Array<Item>): number;
    _encode(value: Array<Item>, writer: Writer): void;
    _decode(reader: Reader): Array<Item>;
}

declare class ArrayVariableCodec<Item> extends AbstractCodec<Array<Item>> {
    readonly itemCodec: AbstractCodec<Item>;
    readonly lengthCodec: AbstractCodec<number>;
    constructor(itemCodec: AbstractCodec<Item>, lengthCodec?: AbstractCodec<number>);
    isValid(value: unknown): value is Array<Item>;
    byteLength(value: Array<Item>): number;
    _encode(value: Array<Item>, writer: Writer): void;
    _decode(reader: Reader): Array<Item>;
}

type ArrayCodec<Item> = ArrayFixedCodec<Item> | ArrayVariableCodec<Item>;
/**
 * Creates a codec for a variable length array.
 *
 * Serializes to ```[LENGTH?][...ITEMS]```
 *
 * Length is present only for variable length arrays.
 *
 * @param	{AbstractCodec} itemCodec - The codec for each item in the array.
 * @param	{AbstractCodec<number>} [lengthCodec="VarInt50()"] - Codec to specify how the length is encoded.
 * @return	{ArrayCodec} ArrayCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/Array/index.ts|Source}
 */
declare function createArrayCodec<Item>(itemCodec: AbstractCodec<Item>, lengthCodec?: AbstractCodec<number>): ArrayVariableCodec<Item>;
/**
 * Creates a codec for a fixed length array.
 *
 * Serializes to ```[LENGTH?][...ITEMS]```
 *
 * Length is present only for variable length arrays.
 *
 * @param	{AbstractCodec} itemCodec - The codec for each item in the array.
 * @param	{number} [length] - Sets a fixed length.
 * @return	{ArrayCodec} ArrayCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/Array/index.ts|Source}
 */
declare function createArrayCodec<Item>(itemCodec: AbstractCodec<Item>, length?: number): ArrayFixedCodec<Item>;

declare const endiannessValues: readonly ["BE", "LE"];
type Endianness = (typeof endiannessValues)[number];
declare const uIntBitValues: readonly [8, 16, 24, 32, 40, 48];
type UIntBits = (typeof uIntBitValues)[number];
type ValidationMode = "both" | "encode" | "decode" | "none";
interface UIntCodecOptions {
    minimum?: number;
    maximum?: number;
    validationMode?: ValidationMode;
}
type UIntCodec = UInt8Codec | UInt16Codec | UInt24Codec | UInt32Codec | UInt40Codec | UInt48Codec;
declare class UInt8Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 1;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(options?: UIntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 1;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class UInt16Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 2;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(endianness?: Endianness, options?: UIntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 2;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class UInt24Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 3;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(endianness?: Endianness, options?: UIntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 3;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class UInt32Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 4;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(endianness?: Endianness, options?: UIntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 4;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class UInt40Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 5;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(endianness?: Endianness, options?: UIntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 5;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class UInt48Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 6;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(endianness?: Endianness, options?: UIntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 6;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}

interface BigUIntCodecOptions {
    minimum?: bigint;
    maximum?: bigint;
    validationMode?: ValidationMode;
}
declare class BigUIntBECodec extends AbstractCodec<bigint> {
    protected readonly options?: BigUIntCodecOptions | undefined;
    static readonly BYTE_LENGTH = 8;
    protected readonly _validateEncode: ((value: bigint) => void) | null;
    protected readonly _validateDecode: ((value: bigint, position: number) => void) | null;
    constructor(options?: BigUIntCodecOptions | undefined);
    isValid(value: unknown): value is bigint;
    byteLength(): 8;
    _encode(value: bigint, writer: Writer): void;
    _decode(reader: Reader): bigint;
}
declare class BigUIntLECodec extends BigUIntBECodec {
    _encode(value: bigint, writer: Writer): void;
    _decode(reader: Reader): bigint;
}

declare class BitFieldCodec<Key extends string> extends AbstractCodec<Record<Key, boolean>> {
    readonly keys: Array<Key>;
    private readonly _byteLength;
    constructor(keys: Array<Key>, _byteLength?: number);
    isValid(value: unknown): value is Record<Key, boolean>;
    byteLength(): number;
    _encode(value: Record<Key, boolean>, writer: Writer): void;
    _decode(reader: Reader): Record<Key, boolean>;
}

declare class BooleanCodec extends AbstractCodec<boolean> {
    isValid(value: unknown): value is boolean;
    byteLength(): 1;
    _encode(value: boolean, writer: Writer): void;
    _decode(reader: Reader): boolean;
}

declare class BytesFixedCodec extends AbstractCodec<Uint8Array> {
    protected _byteLength: number;
    constructor(byteLength: number);
    isValid(value: unknown): value is Uint8Array;
    byteLength(): number;
    _encode(value: Uint8Array, writer: Writer): void;
    _decode(reader: Reader): Uint8Array;
}

declare class BytesConstantCodec extends BytesFixedCodec {
    readonly bytes: Uint8Array;
    readonly constantTime: boolean;
    constructor(bytes: Uint8Array, constantTime?: boolean);
    isValid(value: unknown): value is Uint8Array;
    _encode(_: Uint8Array, writer: Writer): void;
    _decode(reader: Reader): Uint8Array;
}

declare class BytesVariableCodec extends AbstractCodec<Uint8Array> {
    readonly lengthCodec: AbstractCodec<number>;
    constructor(lengthCodec?: AbstractCodec<number>);
    isValid(value: unknown): value is Uint8Array;
    byteLength(value: Uint8Array): number;
    _encode(value: Uint8Array, writer: Writer): void;
    _decode(reader: Reader): Uint8Array;
}

type BytesCodec = BytesFixedCodec | BytesVariableCodec;
/**
 * Creates a codec for a variable length buffer.
 *
 * Serializes to ```[LENGTH?][BUFFER]```
 *
 * @param	{AbstractCodec<number>} [lengthCodec="VarInt50()"] - Codec to specify how the length is encoded.
 * @return	{BytesCodec} BytesCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/Bytes/index.ts|Source}
 */
declare function createBytesCodec(lengthCodec?: AbstractCodec<number>): BytesVariableCodec;
/**
 * Creates a codec for a fixed length buffer.
 *
 * Serializes to ```[BUFFER]```
 *
 * @param	{number} length - Sets a fixed length.
 * @return	{BytesCodec} BytesCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/Bytes/index.ts|Source}
 */
declare function createBytesCodec(length: number): BytesFixedCodec;
/**
 * Creates a codec for a constant buffer.
 *
 * Serializes to ```[BUFFER]```
 *
 * @param	{Uint8Array} bytes - Constant bytes value.
 * @return	{BytesCodec} BytesCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/Bytes/index.ts|Source}
 */
declare function createBytesCodec(bytes: Uint8Array): BytesConstantCodec;

declare class ConstantCodec<const Value> extends AbstractCodec<Value> {
    readonly value: Value;
    constructor(value: Value);
    isValid(value: unknown): value is Value;
    byteLength(): number;
    _encode(_value: Value, _writer: Writer): void;
    _decode(_reader: Reader): Value;
}

declare const floatBitValues: readonly [32, 64];
type FloatBits = (typeof floatBitValues)[number];
interface FloatCodecOptions {
    minimum?: number;
    maximum?: number;
    validationMode?: ValidationMode;
}
type FloatCodec = Float32BECodec | Float32LECodec | Float64BECodec | Float64LECodec;
declare class Float32BECodec extends AbstractCodec<number> {
    protected readonly options?: FloatCodecOptions | undefined;
    static readonly BYTE_LENGTH = 4;
    protected readonly _validateEncode: ((value: number) => void) | null;
    protected readonly _validateDecode: ((value: number, position: number) => void) | null;
    constructor(options?: FloatCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 4;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class Float32LECodec extends Float32BECodec {
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class Float64BECodec extends AbstractCodec<number> {
    protected readonly options?: FloatCodecOptions | undefined;
    static readonly BYTE_LENGTH = 8;
    protected readonly _validateEncode: ((value: number) => void) | null;
    protected readonly _validateDecode: ((value: number, position: number) => void) | null;
    constructor(options?: FloatCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 8;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class Float64LECodec extends Float64BECodec {
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}

interface IntCodecOptions {
    minimum?: number;
    maximum?: number;
    validationMode?: ValidationMode;
}
type IntCodec = Int8Codec | Int16Codec | Int24Codec | Int32Codec | Int40Codec | Int48Codec;
declare class Int8Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 1;
    static readonly OFFSET = 128;
    static readonly MIN_VALUE = -128;
    static readonly MAX_VALUE = 127;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(options?: IntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 1;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class Int16Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 2;
    static readonly OFFSET = 32768;
    static readonly MIN_VALUE = -32768;
    static readonly MAX_VALUE = 32767;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(_bits: Extract<UIntBits, 16>, endianness?: Endianness, options?: IntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 2;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class Int24Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 3;
    static readonly OFFSET = 8388608;
    static readonly MIN_VALUE = -8388608;
    static readonly MAX_VALUE = 8388607;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(_bits: Extract<UIntBits, 24>, endianness?: Endianness, options?: IntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 3;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class Int32Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 4;
    static readonly OFFSET = 2147483648;
    static readonly MIN_VALUE = -2147483648;
    static readonly MAX_VALUE = 2147483647;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(_bits: Extract<UIntBits, 32>, endianness?: Endianness, options?: IntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 4;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class Int40Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 5;
    static readonly OFFSET = 549755813888;
    static readonly MIN_VALUE = -549755813888;
    static readonly MAX_VALUE = 549755813887;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(_bits: Extract<UIntBits, 40>, endianness?: Endianness, options?: IntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 5;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}
declare class Int48Codec extends AbstractCodec<number> {
    private readonly options?;
    static readonly BYTE_LENGTH = 6;
    static readonly OFFSET = 140737488355328;
    static readonly MIN_VALUE = -140737488355328;
    static readonly MAX_VALUE = 140737488355327;
    private readonly _littleEndian;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(_bits: Extract<UIntBits, 48>, endianness?: Endianness, options?: IntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(): 6;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}

declare class NumberFixedCodec extends AbstractCodec<bigint> {
    protected _byteLength: number;
    private _hexCodec;
    constructor(byteLength: number);
    isValid(value: unknown): value is bigint;
    byteLength(): number;
    _encode(value: bigint, writer: Writer): void;
    _decode(reader: Reader): bigint;
}

declare class NumberVariableCodec extends AbstractCodec<bigint> {
    readonly lengthCodec: AbstractCodec<number>;
    private _hexCodec;
    constructor(lengthCodec?: AbstractCodec<number>);
    isValid(value: unknown): value is bigint;
    byteLength(value: bigint): number;
    _encode(value: bigint, writer: Writer): void;
    _decode(reader: Reader): bigint;
}

declare class UnionCodec<const Codecs extends Array<AbstractCodec<any>>> extends AbstractCodec<CodecType<Codecs[number]>> {
    readonly indexCodec: AbstractCodec<number>;
    codecs: Codecs;
    private readonly _matchers;
    protected _undefinedFastPath: boolean;
    constructor(codecs: Codecs, indexCodec?: AbstractCodec<number>);
    /**
     * Returns a new union codec with all nested unions flattened into a single level.
     *
     * Flattening saves 1 byte per level by merging nested union indices into a single index.
     * - Without flattening: `[parentIndex][childIndex][value]` (2+ bytes overhead)
     * - With flattening: `[flatIndex][value]` (1 byte overhead)
     *
     * @example
     * ```ts
     * const inner = Codec.Union([Codec.String(), Codec.UInt(8)]);
     * const outer = Codec.Union([inner, Codec.Boolean]);
     *
     * // Nested encoding (2 bytes overhead for inner union values)
     * outer.encode("hello"); // [0][0][...hello bytes]
     *
     * // Flattened encoding (1 byte overhead)
     * const flat = outer.flatten();
     * flat.encode("hello"); // [0][...hello bytes]
     * ```
     *
     * @return {UnionCodec} A new union codec with nested unions flattened
     */
    flatten(): UnionCodec<Codecs>;
    isValid(value: unknown): value is CodecType<Codecs[number]>;
    byteLength(value: CodecType<Codecs[number]>): number;
    _encode(value: CodecType<Codecs[number]>, writer: Writer): void;
    _decode(reader: Reader): CodecType<Codecs[number]>;
}
declare class OptionalCodec<Value> extends UnionCodec<[AbstractCodec<Value>, ConstantCodec<undefined>]> {
    readonly valueCodec: AbstractCodec<Value>;
    constructor(valueCodec: AbstractCodec<Value>);
}

/**
 * Infers the output object type from codec properties using a single unified type helper.
 * Splits required and optional properties based on OptionalCodec usage.
 */
type OutputObject<T extends Record<string, AbstractCodec>> = {
    [K in keyof T as T[K] extends OptionalCodec<any> ? never : K]: CodecType<T[K]>;
} & {
    [K in keyof T as T[K] extends OptionalCodec<any> ? K : never]?: T[K] extends OptionalCodec<infer V> ? V : never;
};
declare class ObjectCodec<Properties extends Record<string, AbstractCodec>> extends AbstractCodec<OutputObject<Properties>> {
    readonly properties: Properties;
    entries: Array<[keyof Properties, AbstractCodec]>;
    private readonly _plan;
    constructor(properties: Properties);
    isValid(value: unknown): value is OutputObject<Properties>;
    byteLength(value: OutputObject<Properties>): number;
    _encode(value: OutputObject<Properties>, writer: Writer): void;
    _decode(reader: Reader): OutputObject<Properties>;
}

declare class RecordFixedCodec<Key extends string, Value extends any> extends AbstractCodec<Record<Key, Value>> {
    readonly length: number;
    readonly keyCodec: AbstractCodec<Key>;
    readonly valueCodec: AbstractCodec<Value>;
    constructor(length: number, keyCodec: AbstractCodec<Key>, valueCodec: AbstractCodec<Value>);
    isValid(value: unknown): value is Record<Key, Value>;
    byteLength(value: Record<Key, Value>): number;
    _encode(value: Record<Key, Value>, writer: Writer): void;
    _decode(reader: Reader): Record<Key, Value>;
}

declare class RecordVariableCodec<Key extends string, Value extends any> extends AbstractCodec<Record<Key, Value>> {
    readonly keyCodec: AbstractCodec<Key>;
    readonly valueCodec: AbstractCodec<Value>;
    readonly lengthCodec: AbstractCodec<number>;
    constructor(keyCodec: AbstractCodec<Key>, valueCodec: AbstractCodec<Value>, lengthCodec?: AbstractCodec<number>);
    isValid(value: unknown): value is Record<Key, Value>;
    byteLength(value: Record<Key, Value>): number;
    _encode(value: Record<Key, Value>, writer: Writer): void;
    _decode(reader: Reader): Record<Key, Value>;
}

type RecordCodec<Key extends string, Value> = RecordFixedCodec<Key, Value> | RecordVariableCodec<Key, Value>;
/**
 * Creates a codec for a variable size record or map of keys and values.
 *
 * Serializes to ```[LENGTH][...[[KEY][VALUE]]]```
 *
 * Length is present only for variable length records.
 *
 * @param	{AbstractCodec<string>} keyCodec - Codec for keys.
 * @param	{AbstractCodec} valueCodec - Codec for values.
 * @param	{AbstractCodec<number>} [options.lengthCodec="VarUInt()"] - Codec to specify how the length is encoded.
 * @return	{RecordCodec} RecordCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/Record/index.ts|Source}
 */
declare function createRecordCodec<Key extends string, Value>(keyCodec: AbstractCodec<Key>, valueCodec: AbstractCodec<Value>, lengthCodec?: AbstractCodec<number>): RecordVariableCodec<Key, Value>;
/**
 * Creates a codec for a fixed size record or map of keys and values.
 *
 * Serializes to ```[...[[KEY][VALUE]]]```
 *
 * Length is present only for variable length records.
 *
 * @param	{AbstractCodec<string>} keyCodec - Codec for keys.
 * @param	{AbstractCodec} valueCodec - Codec for values.
 * @param	{number} length - Sets a fixed length.
 * @return	{RecordCodec} RecordCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/Record/index.ts|Source}
 */
declare function createRecordCodec<Key extends string, Value>(keyCodec: AbstractCodec<Key>, valueCodec: AbstractCodec<Value>, length: number): RecordFixedCodec<Key, Value>;

declare class RecursiveCodec<const Value> extends AbstractCodec<Value> {
    readonly recursion: (self: DeferredCodec<Value>) => AbstractCodec<Value>;
    readonly codec: AbstractCodec<Value>;
    constructor(recursion: (self: DeferredCodec<Value>) => AbstractCodec<Value>);
    isValid(value: unknown): value is Value;
    byteLength(value: Value): number;
    _encode(value: Value, writer: Writer): void;
    _decode(reader: Reader): Value;
}
declare class DeferredCodec<const Value> extends AbstractCodec<Value> {
    readonly recursiveCodec: RecursiveCodec<Value>;
    constructor(recursiveCodec: RecursiveCodec<Value>);
    isValid(value: unknown): value is Value;
    byteLength(value: Value): number;
    _encode(value: Value, writer: Writer): void;
    _decode(reader: Reader): Value;
}

declare class StringFixedCodec extends AbstractCodec<string> {
    readonly encoding: StringEncoding;
    private _byteLength;
    private _bufferCodec;
    private _encoder;
    private _decoder;
    constructor(byteLength: number, encoding?: StringEncoding);
    isValid(value: unknown): value is string;
    byteLength(): number;
    _encode(value: string, writer: Writer): void;
    _decode(reader: Reader): string;
}

declare class StringVariableCodec extends AbstractCodec<string> {
    readonly encoding: StringEncoding;
    readonly lengthCodec: AbstractCodec<number>;
    private _bufferCodec;
    private _encoder;
    private _decoder;
    private _getByteLength;
    constructor(encoding?: StringEncoding, lengthCodec?: AbstractCodec<number>);
    isValid(value: unknown): value is string;
    byteLength(value: string): number;
    _encode(value: string, writer: Writer): void;
    _decode(reader: Reader): string;
}

type StringEncoding = "hex" | "base32" | "base58" | "base64" | "base64url" | "utf8";
type StringCodec = StringFixedCodec | StringVariableCodec;
/**
 * Creates a codec for a variable length string.
 *
 * Serializes to ```[LENGTH][STRING]```
 *
 * Length is present only for variable length strings.
 *
 * @param	{StringEncoding} [encoding="utf8"] - The strings encoding.
 * @param	{AbstractCodec<number>} [lengthCodec="VarUInt()"] - Codec to specify how the length is encoded.
 * @return	{StringCodec} StringCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/String/index.ts|Source}
 */
declare function createStringCodec(encoding?: StringEncoding, lengthCodec?: AbstractCodec<number>): StringVariableCodec;
/**
 * Creates a codec for a fixed length string.
 *
 * Serializes to ```[STRING]```
 *
 * Length is present only for variable length strings.
 *
 * @param	{StringEncoding} [encoding="utf8"] - The strings encoding.
 * @param	{number} [byteLength] - Sets a fixed byte length.
 * @return	{StringCodec} StringCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/String/index.ts|Source}
 */
declare function createStringCodec(encoding?: StringEncoding, byteLength?: number): StringFixedCodec;

interface TransformCodecOptions<Source, Target> {
    isValid?: (source: unknown) => boolean;
    encode: (source: Source) => Target;
    decode: (target: Target, buffer: Uint8Array) => Source;
}
declare class TransformCodec<Source, Target> extends AbstractCodec<Source> {
    readonly targetCodec: AbstractCodec<Target>;
    private readonly _isSourceValid;
    private readonly _encodeSource;
    private readonly _decodeTarget;
    constructor(targetCodec: AbstractCodec<Target>, options: TransformCodecOptions<Source, Target>);
    isValid(value: unknown): value is Source;
    byteLength(value: Source): number;
    _encode(value: Source, writer: Writer): void;
    _decode(reader: Reader): Source;
}

declare class TupleCodec<Tuple extends [...any[]]> extends AbstractCodec<Tuple> {
    readonly codecs: [
        ...{
            [Index in keyof Tuple]: AbstractCodec<Tuple[Index]>;
        }
    ];
    constructor(codecs: [
        ...{
            [Index in keyof Tuple]: AbstractCodec<Tuple[Index]>;
        }
    ]);
    isValid(value: unknown): value is Tuple;
    byteLength(value: Tuple): number;
    _encode(value: Tuple, writer: Writer): void;
    _decode(reader: Reader): Tuple;
}

declare class VarInt15Codec extends AbstractCodec<number> {
    protected readonly options?: VarIntCodecOptions | undefined;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(options?: VarIntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(value: number): 1 | 2;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}

declare class VarInt30Codec extends AbstractCodec<number> {
    protected readonly options?: VarIntCodecOptions | undefined;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(options?: VarIntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(value: number): 1 | 2 | 3 | 4;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}

declare class VarInt60Codec extends AbstractCodec<number> {
    protected readonly options?: VarIntCodecOptions | undefined;
    private readonly _validateEncode;
    private readonly _validateDecode;
    constructor(options?: VarIntCodecOptions | undefined);
    isValid(value: unknown): value is number;
    byteLength(value: number): 1 | 2 | 3 | 4 | 5 | 6 | 7;
    _encode(value: number, writer: Writer): void;
    _decode(reader: Reader): number;
}

declare const varIntBitValues: readonly [15, 30, 60];
type VarIntBits = (typeof varIntBitValues)[number];
interface VarIntCodecOptions {
    minimum?: number;
    maximum?: number;
    validationMode?: ValidationMode;
}
type VarIntCodec = VarInt15Codec | VarInt30Codec | VarInt60Codec;

type UnionToIntersection<Union> = (Union extends unknown ? (distributedUnion: Union) => void : never) extends (mergedIntersection: infer Intersection) => void ? Intersection & Union : never;

/**
 * Creates a codec for a variable length buffer.
 *
 * Serializes to ```[LENGTH?][BUFFER]```
 *
 * @param	{AbstractCodec<number>} [lengthCodec="VarInt50()"] - Codec to specify how the length is encoded.
 * @return	{NumberCodec} NumberCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/Number/index.ts|Source}
 */
declare function createNumberCodec(lengthCodec?: AbstractCodec<number>): NumberVariableCodec;
/**
 * Creates a codec for a fixed length buffer.
 *
 * Serializes to ```[BUFFER]```
 *
 * @param	{number} length - Sets a fixed length.
 * @return	{NumberCodec} NumberCodec
 *
 * {@link https://github.com/visionsofparadise/bufferfy/blob/main/src/Codecs/Number/index.ts|Source}
 */
declare function createNumberCodec(length: number): NumberFixedCodec;

declare namespace Codec {
    type Type<Codec extends AbstractCodec<any>> = CodecType<Codec>;
}
declare const Codec: {
    Any: <Value = any>(options?: AnyCodecOptions<Value>) => AnyCodec<Value>;
    Array: typeof createArrayCodec;
    BigUInt: (endianness?: Endianness, options?: BigUIntCodecOptions) => BigUIntBECodec;
    BitField: <Key extends string>(keys: Array<Key>, byteLength?: number) => BitFieldCodec<Key>;
    Boolean: BooleanCodec;
    Bytes: typeof createBytesCodec;
    Constant: <const Value>(value: Value) => ConstantCodec<Value>;
    Enum: <const Value>(enumValues: Array<Value>, indexCodec: AbstractCodec<number>) => UnionCodec<ConstantCodec<Value>[]>;
    False: ConstantCodec<false>;
    Float: (bits?: FloatBits, endianness?: Endianness, options?: FloatCodecOptions) => Float32BECodec | Float64BECodec;
    Int: (bits?: UIntBits, endianness?: Endianness, options?: IntCodecOptions) => IntCodec;
    Merge: <const ObjectCodecs extends Array<ObjectCodec<any>>>(objectCodecs: ObjectCodecs) => ObjectCodec<UnionToIntersection<ObjectCodecs[number]["properties"]>>;
    Null: ConstantCodec<null>;
    Nullable: <Value>(codec: AbstractCodec<Value>) => UnionCodec<[AbstractCodec<Value>, ConstantCodec<null>]>;
    Number: typeof createNumberCodec;
    Object: <Properties extends Record<string, AbstractCodec>>(properties: Properties) => ObjectCodec<Properties>;
    Omit: <Properties extends Record<string, AbstractCodec>, Key extends keyof Properties>(objectCodec: ObjectCodec<Properties>, keys: Array<Key>) => ObjectCodec<Omit<Properties, Key>>;
    Optional: <Value>(valueCodec: AbstractCodec<Value>) => OptionalCodec<Value>;
    Pick: <Properties extends Record<string, AbstractCodec>, Key extends keyof Properties>(objectCodec: ObjectCodec<Properties>, keys: Array<Key>) => ObjectCodec<Pick<Properties, Key>>;
    Record: typeof createRecordCodec;
    Recursive: <const Value>(recursion: (self: DeferredCodec<Value>) => AbstractCodec<Value>) => RecursiveCodec<Value>;
    String: typeof createStringCodec;
    Transform: <Source, Target>(targetCodec: AbstractCodec<Target>, options: TransformCodecOptions<Source, Target>) => TransformCodec<Source, Target>;
    True: ConstantCodec<true>;
    Tuple: <Tuple extends [...any[]]>(codecs: [...{ [Index in keyof Tuple]: AbstractCodec<Tuple[Index]>; }]) => TupleCodec<Tuple>;
    UInt: (bits?: UIntBits, endianness?: Endianness, options?: UIntCodecOptions) => UIntCodec;
    Undefined: ConstantCodec<undefined>;
    Union: <const Codecs extends Array<AbstractCodec<any>>>(codecs: Codecs, indexCodec?: AbstractCodec<number>) => UnionCodec<Codecs>;
    VarInt: (bits?: VarIntBits, options?: VarIntCodecOptions) => VarInt15Codec | VarInt30Codec | VarInt60Codec;
};

/**
 * Base error class for all bufferfy errors.
 * Contains optional context about where and why the error occurred.
 */
declare class BufferfyError extends Error {
    readonly codecName?: string | undefined;
    readonly offset?: number | undefined;
    readonly context?: unknown;
    constructor(message: string, codecName?: string | undefined, offset?: number | undefined, context?: unknown);
}
/**
 * Thrown when buffer doesn't have enough bytes remaining for decode operation.
 */
declare class BufferfyByteLengthError extends BufferfyError {
    constructor(required?: number, available?: number, offset?: number);
}
/**
 * Thrown when a value doesn't pass codec validation.
 */
declare class BufferfyValidationError extends BufferfyError {
    constructor(codecName: string, value: unknown);
}
/**
 * Thrown when no codec in a union matches the value.
 */
declare class BufferfyUnionError extends BufferfyError {
    constructor(value: unknown, attemptedCodecs: string[]);
}
/**
 * Thrown when a value or index is out of allowed range.
 */
declare class BufferfyRangeError extends BufferfyError {
    constructor(message: string, codecName: string, value: unknown, limit?: number, offset?: number);
}

export { AbstractCodec, AnyCodec, ArrayCodec, ArrayFixedCodec, ArrayVariableCodec, BigUIntBECodec, BigUIntLECodec, BitFieldCodec, BooleanCodec, BufferfyByteLengthError, BufferfyError, BufferfyRangeError, BufferfyUnionError, BufferfyValidationError, BytesCodec, BytesConstantCodec, BytesFixedCodec, BytesVariableCodec, Codec, ConstantCodec, DeferredCodec, Endianness, Float32BECodec, Float32LECodec, Float64BECodec, Float64LECodec, FloatCodec, Int16Codec, Int24Codec, Int32Codec, Int40Codec, Int48Codec, Int8Codec, IntCodec, NumberFixedCodec, NumberVariableCodec, ObjectCodec, OptionalCodec, RecordCodec, RecordFixedCodec, RecordVariableCodec, RecursiveCodec, StringCodec, StringFixedCodec, StringVariableCodec, TransformCodec, TupleCodec, UInt16Codec, UInt24Codec, UInt32Codec, UInt40Codec, UInt48Codec, UInt8Codec, UIntCodec, UnionCodec, VarInt15Codec, VarInt30Codec, VarInt60Codec, VarIntCodec };
