pub struct ReplayWindow {
max_seq: Option<u32>,
window: u32,
bitmap: u64,
}
impl ReplayWindow {
pub fn new(window: u32) -> Self {
Self {
max_seq: None,
window: std::cmp::min(window, 64),
bitmap: 0,
}
}
pub fn check(&mut self, seq: u32) -> bool {
if self.max_seq.is_none() {
self.max_seq = Some(seq);
self.bitmap = 1;
return true;
}
let max = self.max_seq.unwrap();
let is_ahead = if seq > max {
true
} else if seq == max {
false
} else {
(max as u64) - (seq as u64) > (1u64 << 31)
};
if is_ahead && seq != max {
let forward_dist = if seq > max {
seq.wrapping_sub(max)
} else {
seq.wrapping_add(1)
};
if forward_dist >= 64 {
self.bitmap = 0;
} else {
self.bitmap <<= forward_dist;
}
self.max_seq = Some(seq);
self.bitmap |= 1;
return true;
}
if seq == max {
return (self.bitmap & 1) == 0;
}
let backward_dist = max.wrapping_sub(seq);
if backward_dist > self.window {
return false;
}
if backward_dist >= 64 {
return true;
}
let bit = 1u64 << backward_dist;
if (self.bitmap & bit) != 0 {
return false;
}
self.bitmap |= bit;
true
}
}