/**
 * Per-peer reassembly buffer for fragmented packets.
 *
 * When a sender's logical payload exceeds the MTU it gets split into
 * multiple {@link NetworkPacketType.FRAGMENT} packets, each carrying a
 * `(message_id, chunk_index, total_chunks, chunk_bytes)` tuple. The
 * receiver feeds those tuples to {@link receive}; once all chunks for a
 * `message_id` have arrived, `receive` returns the reassembled bytes
 * for the upper layer to dispatch.
 *
 * Loss recovery via NACK: a partially-received message that doesn't
 * complete within `nack_initial_delay_ms` triggers a NACK back to the
 * sender listing the missing chunk indices. NACK rounds repeat at
 * `nack_resend_interval_ms` up to `nack_max_rounds`; after that the
 * receiver gives up on the message and the sender's retention ages
 * out independently. Wire the per-tick driver via {@link service}.
 *
 * Loss-of-last-resort model: if even the NACK retries fail (link is
 * dead, sender retention was evicted, etc.) the message never
 * completes and FIFO-evicts when the pending cap is hit. Upper layers
 * are still expected to tolerate occasional missing messages — NACK
 * recovers most loss, not all.
 *
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2025
 */
export class FragmentAssembler {
    /**
     * @param {{
     *   max_pending_messages?: number,
     *   max_message_size?: number,
     *   nack_initial_delay_ms?: number,
     *   nack_resend_interval_ms?: number,
     *   nack_max_rounds?: number,
     * }} [options]
     *   `max_pending_messages` caps the number of in-flight reassembly
     *   slots; when full, the oldest pending message is evicted to make
     *   room. `max_message_size` rejects reassembled messages larger than
     *   this many bytes (defensive against a malicious peer or a wedged
     *   sender). The `nack_*` knobs control the retransmit-request timer
     *   driven by {@link service}.
     */
    constructor({ max_pending_messages, max_message_size, nack_initial_delay_ms, nack_resend_interval_ms, nack_max_rounds, }?: {
        max_pending_messages?: number;
        max_message_size?: number;
        nack_initial_delay_ms?: number;
        nack_resend_interval_ms?: number;
        nack_max_rounds?: number;
    });
    /** @type {number} @readonly */
    readonly max_pending_messages: number;
    /** @type {number} @readonly */
    readonly max_message_size: number;
    /** @type {number} @readonly */
    readonly nack_initial_delay_ms: number;
    /** @type {number} @readonly */
    readonly nack_resend_interval_ms: number;
    /** @type {number} @readonly */
    readonly nack_max_rounds: number;
    /**
     * Process an incoming fragment. Returns the reassembled bytes when
     * the message is complete, or null otherwise.
     *
     * @param {number} message_id     sender-assigned message id
     * @param {number} chunk_index    0-based
     * @param {number} total_chunks   expected number of chunks (>= 1)
     * @param {Uint8Array} chunk_bytes  source byte array
     * @param {number} chunk_offset   start offset within `chunk_bytes`
     * @param {number} chunk_length   number of bytes from `chunk_offset` to consume
     * @returns {Uint8Array|null}
     */
    receive(message_id: number, chunk_index: number, total_chunks: number, chunk_bytes: Uint8Array, chunk_offset: number, chunk_length: number): Uint8Array | null;
    /**
     * Per-tick maintenance: drive NACK emission for pending messages
     * whose initial delay has elapsed and whose resend interval has
     * lapsed, and drop messages whose NACK budget is exhausted.
     *
     * On the first service tick that observes a pending entry, its
     * arrival is timestamped (so the initial delay is measured from
     * `now_ms` of that tick rather than from the actual wall-clock
     * arrival of the first chunk — at typical tick rates the difference
     * is one tick, negligible vs. the 100 ms initial delay).
     *
     * `on_nack` is invoked once per eligible message with
     * `(message_id, indices, count)`. The `indices` argument is a
     * reused internal Uint8Array; only `indices[0..count)` is valid
     * and only for the duration of the call.
     *
     * @param {number} now_ms
     * @param {function(number, Uint8Array, number): void} on_nack
     */
    service(now_ms: number, on_nack: (arg0: number, arg1: Uint8Array, arg2: number) => void): void;
    /**
     * Number of in-flight reassembly slots currently held.
     * @returns {number}
     */
    pending_count(): number;
    /**
     * Drop all in-flight reassembly state. Useful on peer disconnect.
     */
    clear(): void;
    #private;
}
//# sourceMappingURL=FragmentAssembler.d.ts.map