/**
 * Client-side Split-Block Bloom Filter (SBBF) construction for the
 * `membership_match(field, {blob}, type=bloom)` filter expression.
 *
 * Building the filter on the client and shipping the compact blob lets large membership
 * sets pass the proxy gRPC receive limit, which a raw value list would exceed: 10M int64
 * values are roughly 90 MB as an `in [...]` list but about 14 MB as a bloom filter. The
 * proxy embeds the blob verbatim after validating the envelope and never rebuilds the
 * filter, so these bytes must match what the other SDKs produce exactly.
 *
 * The bit layout is bit-identical to Arrow C++'s `parquet::BlockSplitBloomFilter`, and thus
 * to the parquet-format BloomFilter.md spec, wrapped in the Milvus MBF1 envelope. See
 * `docs/design-docs/design_docs/20260707-bloom-filter-expression.md` in the milvus repo.
 */
/** The 4-byte MBF1 envelope magic. */
export declare const BLOOM_FILTER_MAGIC = "MBF1";
/** The MBF1 envelope version implemented here. */
export declare const BLOOM_FILTER_VERSION = 1;
/** Identifies the parquet SBBF + XXH64 algorithm. */
export declare const BLOOM_FILTER_ALGO_PARQUET_SBBF_XXH64 = 1;
/** Size in bytes of the MBF1 envelope header. */
export declare const BLOOM_FILTER_HEADER_SIZE = 32;
/** Size of one SBBF block (parquet-format spec). */
export declare const BLOOM_FILTER_BYTES_PER_BLOCK = 32;
/** Marks a filter that recorded int64 values (8-byte little-endian hash domain). */
export declare const BLOOM_FILTER_DOMAIN_INT64 = 1;
/** Marks a filter that recorded string values (raw UTF-8 hash domain). */
export declare const BLOOM_FILTER_DOMAIN_UTF8 = 2;
/**
 * Minimum / maximum filter body size, mirroring Arrow's
 * BlockSplitBloomFilter::kMinimumBloomFilterBytes / kMaximumBloomFilterBytes.
 */
export declare const BLOOM_FILTER_MIN_BYTES = 32;
export declare const BLOOM_FILTER_MAX_BYTES: number;
/** Lowest / highest accepted false-positive rate. */
export declare const BLOOM_FILTER_MIN_FPR = 0.0001;
export declare const BLOOM_FILTER_MAX_FPR = 0.05;
/**
 * Recommended false-positive rate when a caller has no specific target. Sizing follows the
 * Arrow formula, so a body holds roughly 0.72 members per byte at this rate. Bodies are
 * powers of two, so a member count just past a tier boundary doubles the blob; raising fpr
 * is usually the cheaper fix.
 */
export declare const BLOOM_FILTER_DEFAULT_FPR = 0.005;
/**
 * XXH64 with seed 0 over raw bytes — the hash the SBBF spec mandates.
 *
 * BigInt rather than a 32-bit-pair implementation: JavaScript numbers cannot represent a
 * 64-bit hash, and every intermediate here (multiply, rotate) genuinely needs the full
 * width. Build cost is dominated by this, so the int64 domain gets a specialised path below.
 */
export declare const xxh64: (data: Uint8Array) => bigint;
/**
 * XXH64 over an int64's 8-byte little-endian encoding, without materialising those bytes.
 *
 * Specialisation of {@link xxh64} for the one input length the int64 domain ever produces:
 * the 32-byte stripe loop and the 4-byte / 1-byte tails are unreachable, leaving a single
 * 8-byte lane. `value & MASK64` is exactly the little-endian two's-complement encoding read
 * back as a u64, so the pack/unpack round trip drops out.
 */
export declare const xxh64Int64: (value: bigint) => bigint;
/**
 * XXH64 (seed 0) over raw bytes via the 32-bit-pair path, returned as a bigint.
 *
 * This is what {@link BloomFilterBuilder.addString} actually runs; {@link xxh64} is the
 * BigInt reference kept to check it against. Exported so that check can be a test.
 */
export declare const xxh64Pairs: (data: Uint8Array) => bigint;
/**
 * Returns the exact byte length {@link buildBloomFilter} would produce for `n` members at
 * the given false-positive rate, without hashing anything.
 *
 * Use it to check a planned filter against the proxy limits before building it: the body
 * must fit `proxy.maxBloomFilterSize` (64 MiB by default) and the whole request must fit
 * `proxy.grpc.serverMaxRecvSize` (128 MiB by default).
 */
export declare const estimateBloomFilterSize: (n: number, fpr: number) => number;
/**
 * Incrementally constructs an SBBF and serializes it into an MBF1 envelope.
 *
 * Unlike {@link buildBloomFilter} a builder accepts both value domains, producing a filter
 * that matches integer and string members alike — useful for a JSON path that legitimately
 * holds both.
 */
export declare class BloomFilterBuilder {
    private readonly buf;
    private readonly view;
    private readonly numBlocks;
    /** 32 - log2(numBlocks), and numBlocks - 1: together they reduce a hash to a block index. */
    private readonly blockShift;
    private readonly blockMask;
    private readonly nDeclared;
    private readonly fpr;
    private domains;
    /**
     * @param n   expected number of distinct members; it only drives sizing, so inserting more
     *            is allowed and simply raises the effective false-positive rate
     * @param fpr false-positive rate, in [BLOOM_FILTER_MIN_FPR, BLOOM_FILTER_MAX_FPR]
     */
    constructor(n: number, fpr?: number);
    /** Inserts an integer value, hashed as its 8-byte little-endian encoding. */
    addInt64(value: number | bigint): this;
    /**
     * Inserts a string value, hashed as its raw UTF-8 bytes.
     *
     * `Buffer.from` rather than `TextEncoder`: over 10M members the encode step alone is 0.41s
     * via Buffer against 1.48s for a hoisted TextEncoder and 1.81s for a per-call one. Buffer
     * is a Uint8Array subclass, and `xxh64` reads through the view's byteOffset, so the pooled
     * backing store Buffer hands out is handled correctly.
     */
    addString(value: string): this;
    /** Returns the value domains inserted so far. Zero means nothing was inserted. */
    getDomains(): number;
    /** Returns the number of 32-byte blocks in the filter body. */
    getNumBlocks(): number;
    /**
     * Stamps the MBF1 header onto the filter and returns the envelope.
     *
     * The returned array is the builder's own buffer, not a copy, so a filter costs one
     * allocation of its final size rather than a body plus an equal-sized serialization
     * buffer. Treat it as read-only, and copy it if you keep inserting afterwards.
     */
    build(): Uint8Array;
    /**
     * Sets this hash's eight bits directly in the final MBF1 buffer.
     *
     * The block index needs the full 64-bit product, so it stays in BigInt; everything after
     * is 32-bit, where `Math.imul` gives exactly the wrapping multiply the spec wants and
     * `>>> 27` the logical shift.
     */
    private addHash;
}
/**
 * Builds an MBF1-wrapped Split-Block Bloom Filter over a membership set.
 *
 * Members must be homogeneous: either all integers (`number` or `bigint`) or all strings.
 * An empty list produces a valid blob that records no domain and therefore matches nothing.
 *
 * Build the blob from the same value domain as the target field: integer fields hash int64,
 * VARCHAR fields hash UTF-8. The envelope records which domains were inserted, so a
 * wrong-domain blob is rejected by the proxy with a parameter error rather than silently
 * matching nothing.
 *
 * ```ts
 * const blob = buildBloomFilter(userIds);
 * await client.query({
 *   collection_name: 'docs',
 *   filter: 'membership_match(user_id, {bf}, type=bloom)',
 *   exprValues: { bf: blob },
 * });
 * ```
 *
 * @param members the membership set
 * @param fpr     false-positive rate, in [BLOOM_FILTER_MIN_FPR, BLOOM_FILTER_MAX_FPR]
 */
export declare const buildBloomFilter: (members: Array<number | bigint | string>, fpr?: number) => Uint8Array;
