import { Bool, Field, type InferProvable, Option, UInt32, type InferValue, type ProvableHashable, type From, type ProvablePure, type IsPure, MerkleList } from 'o1js';
import { type ProvableHashablePure, type ProvableHashableType, type ProvableHashableWide } from '../o1js-missing.ts';
import { TypeBuilder, TypeBuilderPure } from '../provable-type-builder.ts';
import { StaticArray } from './static-array.ts';
import { type NestedProvableFor } from '../nested.ts';
export { DynamicArray };
export { DynamicArrayBase, provable as provableDynamicArray, type DynamicArrayClass, };
type DynamicArray<T = any, V = any> = DynamicArrayBase<T, V>;
type DynamicArrayClass<T, V> = typeof DynamicArrayBase<T, V> & {
    provable: ProvableHashableWide<DynamicArrayBase<T, V>, V[], (T | V)[]>;
    /**
     * Create a new DynamicArray from an array of values.
     *
     * Note: Both the actual length and the values beyond the original ones will be constant.
     */
    from(v: (T | V)[] | DynamicArrayBase<T, V>): DynamicArrayBase<T, V>;
};
type DynamicArrayClassPure<T, V> = typeof DynamicArrayBase<T, V> & Omit<DynamicArrayClass<T, V>, 'provable'> & {
    provable: ProvableHashableWide<DynamicArrayBase<T, V>, V[], (T | V)[]> & Omit<ProvablePure<DynamicArrayBase<T, V>, V[]>, 'fromValue'>;
};
/**
 * Dynamic-length array type that has a
 * - constant max length, but
 * - dynamic actual length
 *
 * ```ts
 * const Bytes = DynamicArray(UInt8, { maxLength: 32 });
 * ```
 *
 * `maxLength` can be any number from 0 to 2^16-1.
 *
 * **Details**: Internally, this is represented as a static-sized array, plus a Field element
 * that represents the length.
 * The _only_ requirement on these is that the length is less or equal maxLength.
 * In particular, there are no provable guarantees maintained on the content of the static-sized array beyond the actual length.
 * Instead, our methods ensure integrity of array operations _within_ the actual length.
 */
declare function DynamicArray<A extends ProvableHashableType, T extends InferProvable<A> = InferProvable<A>, V extends InferValue<A> = InferValue<A>>(type: A, options: {
    maxLength: number;
}): IsPure<A, Field> extends true ? DynamicArrayClassPure<T, V> : DynamicArrayClass<T, V>;
declare namespace DynamicArray {
    var Base: typeof DynamicArrayBase;
}
declare class DynamicArrayBase<T = any, V = any> {
    /**
     * The internal array, which includes the actual values, padded up to `maxLength` with unconstrained values.
     */
    array: T[];
    /**
     * Length of the array. Guaranteed to be in [0, maxLength].
     */
    length: Field;
    get innerType(): ProvableHashableType<T, V>;
    static get maxLength(): number;
    get maxLength(): number;
    constructor(array: T[], length: Field);
    /**
     * Asserts that 0 <= i < this.length, using a cached check that's not duplicated when doing it on the same variable multiple times.
     *
     * Cost: 1.5
     */
    assertIndexInRange(i: UInt32): void;
    /**
     * Gets value at index i, and proves that the index is in the array.
     *
     * Cost: TN + 1.5
     */
    get(i: UInt32): T;
    /**
     * Gets a value at index i, as an option that is None if the index is not in the array.
     *
     * Note: The correct type for `i` is actually UInt16 which doesn't exist. The method is not complete (but sound) for i >= 2^16.
     *
     * Cost: TN + 2.5
     */
    getOption(i: UInt32): Option<T>;
    /**
     * Gets a value at index i, ASSUMING that the index is in the array.
     *
     * If the index is in fact not in the array, the return value is completely unconstrained.
     *
     * **Warning**: Only use this if you already know/proved by other means that the index is within bounds.
     *
     * Cost: T*N where T = size of the type
     */
    getOrUnconstrained(i: Field): T;
    /**
     * Sets a value at index i and proves that the index is in the array.
     *
     * Cost: 1.5(T + 1)N + 1.5
     */
    set(i: UInt32, value: T): void;
    /**
     * Sets a value at index i, or does nothing if the index is not in the array
     *
     * Cost: 1.5(T + 1)N
     */
    setOrDoNothing(i: Field, value: T): void;
    /**
     * Map every element of the array to a new value.
     *
     * **Warning**: The callback will be passed unconstrained dummy values.
     */
    map<S extends ProvableHashableType>(type: S, f: (t: T, i: number) => From<S>): DynamicArray<InferProvable<S>, InferValue<S>>;
    /**
     * Iterate over all elements of the array.
     *
     * The callback will be passed an element and a boolean `isDummy` indicating whether the value is part of the actual array.
     */
    forEach(f: (t: T, isDummy: Bool, i: number) => void): void;
    /**
     * Iterate over all elements of the array, in reverse order.
     *
     * The callback will be passed an element and a boolean `isDummy` indicating whether the value is part of the actual array.
     *
     * Note: the indices are also passed in reverse order, i.e. we always have `t = this.array[i]`.
     */
    forEachReverse(f: (t: T, isDummy: Bool, i: number) => void): void;
    /**
     * Reduce the array to a single value.
     *
     * The callback will be passed the current state, an element, and a boolean `isDummy` indicating whether the value is part of the actual array.
     */
    reduce<S>(stateType: NestedProvableFor<S>, state: S, f: (state: S, t: T, isDummy: Bool) => S): S;
    /**
     * Split the array at index i, i.e. returns `[slice(0, i), slice(i)]`.
     *
     * If i is 0, the first array will be empty.
     * If i it >= the length, the second array will be empty.
     *
     * Note: this method uses very few constraints, it's only rearranging the array contents
     * and recomputing the two lengths.
     */
    splitAt(i: number): [DynamicArray<T, V>, DynamicArray<T, V>];
    /**
     * Equivalent to `Array.slice(start)`. Supports variable start index.
     */
    slice(start: number | UInt32): DynamicArray<T, V>;
    /**
     * Returns a new array with the elements reversed.
     */
    reverse(): DynamicArray<T, V>;
    /**
     * Dynamic array hash that only depends on the actual values (not the padding).
     *
     * Avoids hash collisions by encoding the number of actual elements at the beginning of the hash input.
     */
    hash(): import("node_modules/o1js/dist/node/lib/provable/field.js").Field;
    /**
     * Convert the array to a MerkleList.
     */
    merkelize(listHash?: (hash: Field, t: T) => Field): MerkleList<T>;
    /**
     * Returns a dynamic number of full chunks and a final, smaller chunk.
     *
     * If the array is evenly divided into chunks, the final chunk has length 0.
     *
     * Note: This method uses very few constraints, it's mostly rearranging the array contents
     * doing a small amount of math on the lengths, and a single `get()` operation on the chunked array.
     */
    chunk(chunkSize: number): [DynamicArray<StaticArray<T, V>, V[]>, DynamicArray<T, V>];
    /**
     * Assert that the array is exactly equal, in its representation in field elements, to another array.
     *
     * Warning: Also checks equality of the padding and maxLength, which don't contribute to the "meaningful" part of the array.
     * Therefore, this method is mainly intended for testing.
     */
    assertEqualsStrict(other: DynamicArray<T, V>): void;
    /**
     * Assert that this array is equal to another.
     *
     * Note: This only requires the length and the actual elements to be equal, not the padding or the maxLength.
     * To check for exact equality, use `assertEqualsStrict()`.
     */
    assertEquals(other: DynamicArray<T, V> | StaticArray<T, V> | (T | V)[]): void;
    /**
     * Concatenate two arrays.
     *
     * The resulting (max)length is the sum of the two individual (max)lengths.
     *
     * **Warning**: This method takes effort proportional to (M + N)*N where M, N are the two maxlengths.
     * It's only recommended to use if at least one of the arrays is small.
     */
    concat(other: DynamicArray<T, V>): DynamicArray<T, V>;
    /**
     * Concatenate two arrays.
     *
     * Alternative to `concat()` that takes effort proportional to (M + N)*M where M, N are the two maxlengths,
     * and also has a better constant.
     *
     * Note: This is better than `concat()` if the arrays are about equal or the first array is smaller.
     * It's worse is the first array is much larger than the second.
     */
    concatTransposed(other: DynamicArray<T, V> | StaticArray<T, V>): DynamicArray<T, V>;
    /**
     * Concatenate two arrays.
     *
     * Alternative to `concat()` that proves correctness of the concatenated array
     * by Poseidon-hashing it element by element. In contrast to `concat()`, the effort is linear in N + M,
     * but with a larger constant.
     *
     * The resulting (max)length is the sum of the two individual (max)lengths.
     */
    concatByHashing(other: DynamicArray<T, V>): DynamicArray<T, V>;
    /**
     * Push a value, without changing the maxLength.
     *
     * Proves that the new length is still within the maxLength, fails otherwise.
     *
     * To grow the maxLength along with the actual length, you can use:
     *
     * ```ts
     * array = array.growMaxLengthBy(1);
     * array.push(value);
     * ```
     *
     * Cost: 1.5(T + 1)N + 2
     */
    push(value: T): void;
    /**
     * Return a version of the same array with a larger maxLength.
     *
     * **Warning**: Does not modify the array, but returns a new one.
     *
     * **Note**: this doesn't cost constraints, but currently doesn't preserve any cached constraints.
     */
    growMaxLengthTo(maxLength: number): DynamicArray<T, V>;
    /**
     * Return a version of the same array with a larger maxLength.
     *
     * **Warning**: Does not modify the array, but returns a new one.
     *
     * **Note**: this doesn't cost constraints, but currently doesn't preserve any cached constraints.
     */
    growMaxLengthBy(maxLength: number): DynamicArray<T, V>;
    /**
     * Mutate this array such that all elements beyond the actual length are set to an empty value.
     */
    normalize(): void;
    /**
     * Assert that the array is normalized, i.e. all padding elements are empty.
     *
     * Note: For completeness, it is probably better to use `normalize()` which uses the same amount
     * of constraints and comes with the same guarantee.
     */
    assertNormalized(): void;
    _indexMasks: Map<Field, Bool[]>;
    _indicesInRange: Set<Field>;
    __dummyMask?: Bool[];
    /**
     * Compute i.equals(j) for all indices j in the static-size array.
     *
     * Costs: 1.5N
     *
     * TODO: equals() could be optimized to just 1 double generic because j is constant, o1js doesn't do that
     */
    _indexMask(i: Field): import("node_modules/o1js/dist/node/lib/provable/bool.js").Bool[];
    /**
     * Tells us which elements are dummies = not actually in the array.
     *
     * 0 0 0 1 1 1 1
     *       ^
     *       length
     */
    _dummyMask(): import("node_modules/o1js/dist/node/lib/provable/bool.js").Bool[];
    /**
     * Returns true if the index is a dummy index,
     * i.e. not actually in the array.
     */
    isDummyIndex(i: number): import("node_modules/o1js/dist/node/lib/provable/bool.js").Bool | undefined;
    toValue(): V[];
    /**
     * Assert that this array contains the given subarray, and returns the index where it starts.
     */
    assertContains(subarray: DynamicArray<T, V> | StaticArray<T, V>, message?: string): import("node_modules/o1js/dist/node/lib/provable/field.js").Field;
}
declare function provable<T, V, Class extends typeof DynamicArrayBase<T, V>>(type: ProvableHashablePure<T, V>, Class: Class): TypeBuilderPure<InstanceType<Class>, V[]>;
declare function provable<T, V, Class extends typeof DynamicArrayBase<T, V>>(type: ProvableHashable<T, V>, Class: Class): TypeBuilder<InstanceType<Class>, V[]>;
