pub const WINDOW_BITS: usize = 1024;
const WINDOW_WORDS: usize = WINDOW_BITS / 64;
#[derive(Debug)]
pub struct ReplayWindow {
bitmap: [u64; WINDOW_WORDS],
high_watermark: u32,
initialized: bool,
}
impl Default for ReplayWindow {
fn default() -> Self {
Self::new()
}
}
impl ReplayWindow {
pub const fn new() -> Self {
Self {
bitmap: [0u64; WINDOW_WORDS],
high_watermark: 0,
initialized: false,
}
}
pub fn accept(&mut self, seq: u32) -> bool {
if !self.initialized {
self.high_watermark = seq;
self.bitmap[0] = 1; self.initialized = true;
return true;
}
if seq > self.high_watermark {
let shift = (seq - self.high_watermark) as usize;
if shift >= WINDOW_BITS {
self.bitmap = [0u64; WINDOW_WORDS];
} else {
Self::shift_left(&mut self.bitmap, shift);
}
self.bitmap[0] |= 1; self.high_watermark = seq;
true
} else {
let offset = (self.high_watermark - seq) as usize;
if offset >= WINDOW_BITS {
return false; }
let word = offset / 64;
let bit = offset % 64;
let mask = 1u64 << bit;
if self.bitmap[word] & mask != 0 {
false } else {
self.bitmap[word] |= mask;
true
}
}
}
pub fn high_watermark(&self) -> u32 {
self.high_watermark
}
pub fn is_initialized(&self) -> bool {
self.initialized
}
fn shift_left(bitmap: &mut [u64; WINDOW_WORDS], shift: usize) {
debug_assert!(shift < WINDOW_BITS);
let word_shift = shift / 64;
let bit_shift = shift % 64;
if word_shift > 0 {
for i in (word_shift..WINDOW_WORDS).rev() {
bitmap[i] = bitmap[i - word_shift];
}
for word in bitmap[..word_shift].iter_mut() {
*word = 0;
}
}
if bit_shift > 0 {
let inv = 64 - bit_shift;
for i in (1..WINDOW_WORDS).rev() {
bitmap[i] = (bitmap[i] << bit_shift) | (bitmap[i - 1] >> inv);
}
bitmap[0] <<= bit_shift;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn first_packet_always_accepted() {
let mut w = ReplayWindow::new();
assert!(w.accept(42));
assert!(w.is_initialized());
assert_eq!(w.high_watermark(), 42);
}
#[test]
fn duplicate_is_rejected() {
let mut w = ReplayWindow::new();
assert!(w.accept(10));
assert!(!w.accept(10));
}
#[test]
fn monotonic_sequence_accepted() {
let mut w = ReplayWindow::new();
for seq in 1..=2000u32 {
assert!(w.accept(seq), "seq {} must be accepted", seq);
}
assert_eq!(w.high_watermark(), 2000);
}
#[test]
fn out_of_order_within_window_accepted_once() {
let mut w = ReplayWindow::new();
assert!(w.accept(100));
assert!(w.accept(90)); assert!(!w.accept(90)); assert!(w.accept(80));
assert!(!w.accept(80));
assert!(w.accept(99));
assert!(!w.accept(99));
assert_eq!(w.high_watermark(), 100);
}
#[test]
fn ancient_packet_rejected() {
let mut w = ReplayWindow::new();
assert!(w.accept(2000));
assert!(w.accept(977));
assert!(!w.accept(976));
assert!(!w.accept(100));
assert!(!w.accept(0));
}
#[test]
fn large_forward_jump_resets_window() {
let mut w = ReplayWindow::new();
assert!(w.accept(1));
assert!(w.accept(10_000)); assert_eq!(w.high_watermark(), 10_000);
assert!(!w.accept(1));
assert!(w.accept(9_000));
assert!(!w.accept(9_000));
}
#[test]
fn shift_within_word() {
let mut w = ReplayWindow::new();
assert!(w.accept(5));
assert!(w.accept(10)); assert!(!w.accept(5));
assert!(!w.accept(10));
}
#[test]
fn shift_across_word_boundary() {
let mut w = ReplayWindow::new();
assert!(w.accept(0));
assert!(w.accept(64)); assert!(!w.accept(64));
assert!(!w.accept(0));
assert!(w.accept(32));
assert!(!w.accept(32));
}
#[test]
fn shift_multiple_words() {
let mut w = ReplayWindow::new();
assert!(w.accept(0));
assert!(w.accept(100)); assert!(!w.accept(0));
assert!(!w.accept(100));
assert!(w.accept(50));
assert!(!w.accept(50));
}
#[test]
fn boundary_exactly_at_window_edge() {
let mut w = ReplayWindow::new();
assert!(w.accept(WINDOW_BITS as u32));
assert!(w.accept(1));
assert!(!w.accept(0));
}
}