use crate::wrapping_number::{sequence_greater_than, sequence_less_than};
pub type SequenceNumber = u16;
pub struct SequenceBuffer<T> {
sequence_num: SequenceNumber,
entry_sequences: Box<[Option<SequenceNumber>]>,
entries: Box<[Option<T>]>,
}
impl<T> SequenceBuffer<T> {
pub fn with_capacity(size: u16) -> Self {
let mut entries = Vec::<Option<T>>::new();
for _ in 0..size {
entries.push(None);
}
Self {
sequence_num: 0,
entry_sequences: vec![None; size as usize].into_boxed_slice(),
entries: entries.into_boxed_slice(),
}
}
pub fn sequence_num(&self) -> SequenceNumber {
self.sequence_num
}
pub fn insert(&mut self, sequence_num: SequenceNumber, entry: T) -> bool {
if sequence_less_than(
sequence_num,
self.sequence_num
.wrapping_sub(self.entry_sequences.len() as u16),
) {
return false;
}
self.advance_sequence(sequence_num);
let index = self.index(sequence_num);
self.entry_sequences[index] = Some(sequence_num);
self.entries[index] = Some(entry);
true
}
pub fn exists(&self, sequence_num: SequenceNumber) -> bool {
let index = self.index(sequence_num);
if let Some(s) = self.entry_sequences[index] {
return s == sequence_num;
}
false
}
pub fn remove(&mut self, sequence_num: SequenceNumber) -> Option<T> {
if self.exists(sequence_num) {
let index = self.index(sequence_num);
let value = std::mem::replace(&mut self.entries[index], None);
self.entry_sequences[index] = None;
return value;
}
None
}
fn advance_sequence(&mut self, sequence_num: SequenceNumber) {
if sequence_greater_than(sequence_num.wrapping_add(1), self.sequence_num) {
self.remove_entries(u32::from(sequence_num));
self.sequence_num = sequence_num.wrapping_add(1);
}
}
fn remove_entries(&mut self, mut finish_sequence: u32) {
let start_sequence = u32::from(self.sequence_num);
if finish_sequence < start_sequence {
finish_sequence += 65536;
}
if finish_sequence - start_sequence < self.entry_sequences.len() as u32 {
for sequence in start_sequence..=finish_sequence {
self.remove(sequence as u16);
}
} else {
for index in 0..self.entry_sequences.len() {
self.entries[index] = None;
self.entry_sequences[index] = None;
}
}
}
fn index(&self, sequence: SequenceNumber) -> usize {
sequence as usize % self.entry_sequences.len()
}
}