import { Decoder, FixedSizeDecoder, VariableSizeDecoder } from '@solana/codecs-core';
import { DrainOuterGeneric } from './utils';
/**
 * A function that builds a {@link Decoder} for a struct field whose shape
 * depends on the values of previously decoded fields in the same struct.
 *
 * The function receives a frozen snapshot of all fields that have been decoded
 * so far, in declaration order, and must return the {@link Decoder} that should
 * be used to read the current field from the byte stream.
 *
 * @typeParam TPriorFields - The shape of the fields that have already been
 *     decoded by the time this factory is invoked.
 * @typeParam TValue - The type of the value produced by the returned decoder.
 *
 * @see {@link createDependentStructDecoder}
 */
export type DependentStructDecoderFieldFactory<TPriorFields extends Record<string, unknown>, TValue> = (fields: Readonly<TPriorFields>) => Decoder<TValue>;
/**
 * A fluent builder that accumulates field decoders for a struct whose later
 * fields may depend on the values of earlier ones.
 *
 * Each call to {@link DependentStructDecoderBuilder.field | `field`} returns a
 * new builder whose accumulated field type is widened by the newly added field.
 * Call {@link DependentStructDecoderBuilder.build | `build`} to obtain the
 * final {@link Decoder} once every field has been declared.
 *
 * The builder tracks at the type level whether the struct decoded so far has a
 * fixed size. Adding a {@link FixedSizeDecoder} preserves that property, while
 * adding a {@link VariableSizeDecoder} or a {@link DependentStructDecoderFieldFactory | field factory}
 * drops the builder to variable size and it stays variable thereafter.
 *
 * Instances of this type are immutable. Calling `field` does not mutate the
 * receiver; it returns a new builder.
 *
 * @typeParam TFields - The shape of the struct that has been accumulated so far.
 * @typeParam TIsFixedSize - `true` while every field added so far is a
 *     {@link FixedSizeDecoder}, `false` once any variable size decoder or
 *     factory has been added.
 *
 * @see {@link createDependentStructDecoder}
 */
export type DependentStructDecoderBuilder<TFields extends Record<string, unknown>, TIsFixedSize extends boolean> = {
    /**
     * Finalizes the builder and returns a {@link Decoder} that decodes each
     * declared field in turn, in the order they were added.
     *
     * Returns a {@link FixedSizeDecoder} when every field has been added with a
     * fixed size decoder, and a {@link VariableSizeDecoder} otherwise.
     */
    build(): TIsFixedSize extends true ? FixedSizeDecoder<DrainOuterGeneric<TFields>> : VariableSizeDecoder<DrainOuterGeneric<TFields>>;
    /**
     * Adds a field decoded by a {@link VariableSizeDecoder}. Drops the builder
     * to variable size; subsequent {@link field} calls cannot raise it back to
     * fixed size.
     *
     * Adding a field that has already been declared on this builder is a
     * compile time error.
     */
    field<TName extends string, TValue>(name: TName extends keyof TFields ? never : TName, decoder: VariableSizeDecoder<TValue>): DependentStructDecoderBuilder<DrainOuterGeneric<TFields & {
        [K in TName]: TValue;
    }>, false>;
    /**
     * Adds a field whose decoder is built from a frozen snapshot of the fields
     * that precede it. Drops the builder to variable size since the byte
     * length of the produced decoder cannot be known at type time.
     *
     * Adding a field that has already been declared on this builder is a
     * compile time error.
     */
    field<TName extends string, TValue>(name: TName extends keyof TFields ? never : TName, factory: DependentStructDecoderFieldFactory<TFields, TValue>): DependentStructDecoderBuilder<DrainOuterGeneric<TFields & {
        [K in TName]: TValue;
    }>, false>;
    /**
     * Adds a field decoded by a {@link FixedSizeDecoder}. Preserves the fixed
     * size property of the builder.
     *
     * Adding a field that has already been declared on this builder is a
     * compile time error.
     */
    field<TName extends string, TValue>(name: TName extends keyof TFields ? never : TName, decoder: FixedSizeDecoder<TValue>): DependentStructDecoderBuilder<DrainOuterGeneric<TFields & {
        [K in TName]: TValue;
    }>, TIsFixedSize>;
};
/**
 * Creates a fluent builder for a struct decoder whose later fields may depend
 * on the decoded values of earlier ones.
 *
 * Unlike {@link getStructDecoder}, which accepts a fixed array of named
 * decoders, this builder lets each field provide a factory that receives the
 * values that have already been decoded. This is useful for binary formats
 * where a count, version, or discriminator decoded near the start of the
 * struct controls how a later field must be parsed.
 *
 * The builder mirrors the fixed vs variable size behaviour of
 * {@link getStructDecoder}. The empty builder finishes to a
 * {@link FixedSizeDecoder} of size zero. Adding a {@link FixedSizeDecoder}
 * preserves the fixed size property and the sizes accumulate. Adding a
 * {@link VariableSizeDecoder} or a {@link DependentStructDecoderFieldFactory | field factory}
 * drops the builder to variable size, which is then preserved by every
 * subsequent {@link DependentStructDecoderBuilder.field | `field`} call.
 *
 * The returned builder is immutable; each {@link DependentStructDecoderBuilder.field | `field`}
 * call returns a new builder whose accumulated field type is widened by the
 * newly added field. Call {@link DependentStructDecoderBuilder.build | `build`}
 * to produce the final decoder.
 *
 * @remarks
 * Prefer {@link getStructDecoder} when every field's decoder is independent of
 * the values that precede it. Reach for this builder only when at least one
 * field needs to be parameterised by another.
 *
 * The encoder direction does not need a dependent variant. An encoder already
 * has access to the entire value when serialising, so the existing
 * {@link getStructEncoder} can be paired with the decoder returned by this
 * builder and combined with `combineCodec` to obtain a full codec.
 *
 * @example
 * Decoding a struct whose array length is read from an earlier field.
 * ```ts
 * import { getArrayDecoder } from '@solana/codecs-data-structures';
 * import { getU8Decoder, getU32Decoder } from '@solana/codecs-numbers';
 *
 * const decoder = createDependentStructDecoder()
 *     .field('count', getU8Decoder())
 *     .field('values', fields => getArrayDecoder(getU32Decoder(), { size: fields.count }))
 *     .build();
 *
 * decoder.decode(new Uint8Array([0x02, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00]));
 * // { count: 2, values: [1, 2] }
 * ```
 *
 * @example
 * Mixing static and dependent fields, with a discriminator selecting the payload decoder.
 * ```ts
 * const decoder = createDependentStructDecoder()
 *     .field('version', getU8Decoder())
 *     .field('header', fields => fields.version === 0 ? getU16Decoder() : getU32Decoder())
 *     .build();
 * ```
 *
 * @example
 * Combining the dependent decoder with a static encoder to obtain a full codec.
 * ```ts
 * import { combineCodec } from '@solana/codecs-core';
 *
 * const encoder = getStructEncoder([
 *     ['count', getU8Encoder()],
 *     ['values', getArrayEncoder(getU32Encoder())],
 * ]);
 * const decoder = createDependentStructDecoder()
 *     .field('count', getU8Decoder())
 *     .field('values', fields => getArrayDecoder(getU32Decoder(), { size: fields.count }))
 *     .build();
 * const codec = combineCodec(encoder, decoder);
 * ```
 *
 * @see {@link getStructDecoder}
 * @see {@link getStructEncoder}
 */
export declare function createDependentStructDecoder(): DependentStructDecoderBuilder<Record<never, never>, true>;
//# sourceMappingURL=dependent-struct.d.ts.map