/**
 * @license
 * Copyright 2022-2025 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Bytes, Merge } from "#general";
import { LengthConstraints } from "./TlvArray.js";
import { TlvTag, TlvType, TlvTypeLength } from "./TlvCodec.js";
import { TlvEncodingOptions, TlvReader, TlvSchema, TlvWriter } from "./TlvSchema.js";
export interface FieldType<T> {
    id: number;
    schema: TlvSchema<T>;
    optional?: boolean;
    repeated?: boolean;
    fallback?: T;
}
export interface RepeatedFieldType<T> extends FieldType<T> {
    repeated: true;
    minLength?: number;
    maxLength?: number;
}
export interface OptionalFieldType<T> extends FieldType<T> {
    optional: true;
}
export interface OptionalRepeatedFieldType<T> extends OptionalFieldType<T> {
    repeated: true;
    maxLength?: number;
}
export type TlvFields = {
    [field: string]: FieldType<any>;
};
type MandatoryFieldNames<F extends TlvFields> = {
    [K in keyof F]: F[K] extends OptionalFieldType<any> ? never : K;
}[keyof F];
type OptionalFieldNames<F extends TlvFields> = {
    [K in keyof F]: F[K] extends OptionalFieldType<any> ? K : never;
}[keyof F];
type TypeFromField<F extends FieldType<any>> = F extends FieldType<infer T> ? T : never;
type TypeForMandatoryFields<F extends TlvFields, MF extends keyof F> = {
    [K in MF]: TypeFromField<F[K]>;
};
type TypeForOptionalFields<F extends TlvFields, MF extends keyof F> = {
    [K in MF]?: TypeFromField<F[K]>;
};
export type TypeFromFields<F extends TlvFields> = Merge<TypeForMandatoryFields<F, MandatoryFieldNames<F>>, TypeForOptionalFields<F, OptionalFieldNames<F>>>;
/**
 * Schema to encode an object in TLV.
 *
 * @see {@link MatterSpecification.v10.Core} § A.5.1 and § A.11.4
 */
export declare class ObjectSchema<F extends TlvFields> extends TlvSchema<TypeFromFields<F>> {
    #private;
    private readonly fieldDefinitions;
    private readonly type;
    private readonly allowProtocolSpecificTags;
    readonly isFabricScoped: boolean;
    private readonly fieldById;
    constructor(fieldDefinitions: F, type?: TlvType.Structure | TlvType.List, allowProtocolSpecificTags?: boolean);
    encodeTlvInternal(writer: TlvWriter, value: TypeFromFields<F>, tag?: TlvTag, options?: TlvEncodingOptions): void;
    decodeTlvInternalValue(reader: TlvReader, typeLength: TlvTypeLength): TypeFromFields<F>;
    validate(value: TypeFromFields<F>): void;
    injectField(value: TypeFromFields<F>, fieldId: number, fieldValue: any, injectChecker: (fieldValue: any) => boolean): TypeFromFields<F>;
    removeField(value: TypeFromFields<F>, fieldId: number, removeChecker: (fieldValue: any) => boolean): TypeFromFields<F>;
}
/** Object TLV schema. */
export declare const TlvObject: <F extends TlvFields>(fields: F) => ObjectSchema<F>;
export declare class ObjectSchemaWithMaxSize<F extends TlvFields> extends ObjectSchema<F> {
    protected readonly maxSize: number;
    constructor(fieldDefinitions: F, maxSize: number, type?: TlvType.Structure | TlvType.List, allowProtocolSpecificTags?: boolean);
    encode(value: TypeFromFields<F>): Bytes;
}
export declare const TlvObjectWithMaxSize: <F extends TlvFields>(fields: F, maxSize: number) => ObjectSchemaWithMaxSize<F>;
/**
 * List TLV schema with all tagged entries.
 * List entries that can appear multiple times can be defined using TlvRepeatedField/TlvOptionalRepeatedField and are
 * represented as Arrays.
 * TODO: We represent Tlv Lists right now as named object properties. This formally does not match the spec, which
 *      defines a list as a sequence of TLV elements with optional tag where the order matters. That's ok for now
 *      (also with the help of "Repeated Fields") because it not makes any real difference for now for the current
 *      existing data structures. We need to change once this changes.
 */
export declare const TlvTaggedList: <F extends TlvFields>(fields: F, allowProtocolSpecificTags?: boolean) => ObjectSchema<F>;
/**
 * Object TLV mandatory field. Optionally provide a fallback value to initialize the field value when devices omit
 * providing a value against the specifications or in special use cases. Make sure to use a value that is an equivalent
 * to the value being empty.
 */
export declare const TlvField: <T>(id: number, schema: TlvSchema<T>, fallback?: T) => FieldType<T>;
/** Object TLV optional field. */
export declare const TlvOptionalField: <T>(id: number, schema: TlvSchema<T>) => OptionalFieldType<T>;
/**
 * Object TLV mandatory field that can exist repeated in a TLV List structure. The order is preserved on encoding and
 * decoding.
 */
export declare const TlvRepeatedField: <T>(id: number, schema: TlvSchema<T>, lengthOptions?: LengthConstraints) => RepeatedFieldType<T[]>;
/**
 * Object TLV optional field that can exist repeated in a TLV List structure. The order is preserved on encoding and
 * decoding.
 */
export declare const TlvOptionalRepeatedField: <T>(id: number, schema: TlvSchema<T>, lengthOptions?: {
    maxLength: number;
}) => OptionalRepeatedFieldType<T[]>;
export {};
//# sourceMappingURL=TlvObject.d.ts.map