#[derive(Debug, Clone)]
pub struct UnsequencedState {
incoming_unsequenced_group: u16,
unsequenced_window: [u32; 32], outgoing_unsequenced_group: u16,
}
impl Default for UnsequencedState {
fn default() -> Self {
Self::new()
}
}
impl UnsequencedState {
pub fn new() -> Self {
Self {
incoming_unsequenced_group: 0,
unsequenced_window: [0; 32], outgoing_unsequenced_group: 0,
}
}
pub fn next_outgoing_group(&mut self) -> u16 {
let group = self.outgoing_unsequenced_group;
self.outgoing_unsequenced_group = self.outgoing_unsequenced_group.wrapping_add(1);
group
}
pub fn incoming_group(&self) -> u16 {
self.incoming_unsequenced_group
}
pub fn outgoing_group(&self) -> u16 {
self.outgoing_unsequenced_group
}
pub fn is_duplicate(&self, group: u16) -> bool {
let window_empty = self.unsequenced_window.iter().all(|&w| w == 0);
if window_empty {
return false;
}
let offset = group.wrapping_sub(self.incoming_unsequenced_group);
if offset < 1024 {
let word_index = (offset / 32) as usize;
let bit_index = offset % 32;
if word_index < 32 {
return (self.unsequenced_window[word_index] & (1 << bit_index)) != 0;
}
}
if offset > 32768 {
return true; }
false
}
pub fn mark_received(&mut self, group: u16) {
let offset = group.wrapping_sub(self.incoming_unsequenced_group);
if (1024..=32768).contains(&offset) {
let advance = offset.saturating_sub(512);
let word_shift = (advance / 32) as usize;
let bit_shift = advance % 32;
if word_shift > 0 {
if word_shift >= 32 {
self.unsequenced_window = [0; 32];
} else {
for i in 0..(32 - word_shift) {
self.unsequenced_window[i] = self.unsequenced_window[i + word_shift];
}
for i in (32 - word_shift)..32 {
self.unsequenced_window[i] = 0;
}
}
}
if bit_shift > 0 && word_shift < 32 {
for i in 0..31 {
self.unsequenced_window[i] = (self.unsequenced_window[i] >> bit_shift)
| (self.unsequenced_window[i + 1] << (32 - bit_shift));
}
self.unsequenced_window[31] >>= bit_shift;
}
self.incoming_unsequenced_group = self.incoming_unsequenced_group.wrapping_add(advance);
}
let final_offset = group.wrapping_sub(self.incoming_unsequenced_group);
if final_offset < 1024 {
let word_index = (final_offset / 32) as usize;
let bit_index = final_offset % 32;
if word_index < 32 {
self.unsequenced_window[word_index] |= 1 << bit_index;
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_unsequenced_window_sliding() {
let mut state = UnsequencedState::new();
assert!(!state.is_duplicate(0));
state.mark_received(0);
assert!(state.is_duplicate(0));
assert!(!state.is_duplicate(1500));
state.mark_received(1500);
assert!(state.is_duplicate(0));
}
#[test]
fn test_unsequenced_window_wrapping() {
let mut state = UnsequencedState::new();
for i in 0..3 {
let group = 65000 + i;
assert!(!state.is_duplicate(group));
state.mark_received(group);
}
assert!(!state.is_duplicate(65500));
state.mark_received(65500);
assert!(!state.is_duplicate(10));
state.mark_received(10);
assert!(state.is_duplicate(65002));
}
#[test]
fn test_unsequenced_basic_duplicate_detection() {
let mut state = UnsequencedState::new();
assert!(!state.is_duplicate(5));
state.mark_received(5);
assert!(state.is_duplicate(5));
assert!(!state.is_duplicate(10));
state.mark_received(10);
assert!(state.is_duplicate(5));
assert!(state.is_duplicate(10));
}
#[test]
fn test_unsequenced_window_boundaries() {
let mut state = UnsequencedState::new();
state.mark_received(100);
assert!(!state.is_duplicate(1123));
state.mark_received(1123);
assert!(state.is_duplicate(1123));
assert!(!state.is_duplicate(1124));
state.mark_received(1124);
assert!(state.is_duplicate(100));
}
#[test]
fn test_next_outgoing_group() {
let mut state = UnsequencedState::new();
assert_eq!(state.next_outgoing_group(), 0);
assert_eq!(state.next_outgoing_group(), 1);
assert_eq!(state.next_outgoing_group(), 2);
state.outgoing_unsequenced_group = 65535;
assert_eq!(state.next_outgoing_group(), 65535);
assert_eq!(state.next_outgoing_group(), 0);
}
#[test]
fn test_getters() {
let mut state = UnsequencedState::new();
assert_eq!(state.incoming_group(), 0);
assert_eq!(state.outgoing_group(), 0);
state.mark_received(100);
assert_eq!(state.incoming_group(), 0);
state.mark_received(1500); assert!(state.incoming_group() > 0);
state.next_outgoing_group();
assert_eq!(state.outgoing_group(), 1);
}
#[test]
fn test_empty_window() {
let state = UnsequencedState::new();
assert!(!state.is_duplicate(0));
assert!(!state.is_duplicate(100));
assert!(!state.is_duplicate(65535));
}
#[test]
fn test_complete_window_reset() {
let mut state = UnsequencedState::new();
state.mark_received(0);
state.mark_received(1);
state.mark_received(2);
state.mark_received(2000);
assert!(state.is_duplicate(0));
assert!(state.is_duplicate(1));
assert!(state.is_duplicate(2));
assert!(!state.is_duplicate(2001));
state.mark_received(2001);
assert!(state.is_duplicate(2001));
}
}