import Foundation
/// Best-effort in-session replay suppression for one remote sender and key.
/// IVs are epoch ‖ counter. Within an epoch a sliding window of the last 64
/// counters is tracked (as in DTLS/IPsec anti-replay): a counter is accepted if
/// it is new and not more than 64 behind the highest seen — so frames that were
/// sealed concurrently and delivered out of order still pass, while duplicates
/// and stale replays do not. A retired epoch never comes back.
public struct ReplayWindow: Sendable {
public static let retiredEpochsKept = 8
public static let windowSize: UInt64 = 64
private var epoch: Data?
private var highest: UInt64 = 0
/// Bit i set ⇔ counter `highest - i` has been seen (bit 0 is `highest` itself).
private var seen: UInt64 = 0
private var retired: [Data] = []
public init() {}
/// Returns `true` if the IV is fresh (and records it), `false` for a replay or a stale counter.
public mutating func accept(iv: Data) -> Bool {
guard iv.count == 12 else { return false }
let e = Data(iv.prefix(4))
let c = iv.suffix(8).reduce(UInt64(0)) { ($0 << 8) | UInt64($1) }
if let current = epoch {
if e != current {
if retired.contains(e) { return false }
retired.append(current)
if retired.count > ReplayWindow.retiredEpochsKept { retired.removeFirst() }
epoch = e
highest = c
seen = 1
return true
}
if c > highest {
let shift = c - highest
seen = shift >= 64 ? 1 : (seen << shift) | 1
highest = c
return true
}
let behind = highest - c
guard behind < ReplayWindow.windowSize else { return false }
let bit: UInt64 = 1 << behind
guard seen & bit == 0 else { return false }
seen |= bit
return true
}
epoch = e
highest = c
seen = 1
return true
}
}