use std::{
collections::VecDeque,
time::{Duration, Instant},
};
pub const ENFORCED_SIZE_TIME: u64 = 1;
pub struct ReceivedPacket<T> {
pub content: T,
pub received: Instant,
}
pub struct ReceivedPacketCache<T> {
target: usize,
time_window: u64,
within_enforced_time: usize,
inner: VecDeque<ReceivedPacket<T>>,
}
impl<T> ReceivedPacketCache<T> {
pub fn new(target: usize, time_window: u64) -> Self {
Self {
target,
time_window,
within_enforced_time: 0,
inner: VecDeque::with_capacity(target * time_window as usize),
}
}
pub fn reset(&mut self) {
while let Some(packet) = self.inner.pop_front() {
if packet.received > Instant::now() - Duration::from_secs(self.time_window) {
self.inner.push_front(packet);
break;
}
}
let mut count = 0;
for packet in self.inner.iter().rev() {
if packet.received > Instant::now() - Duration::from_secs(ENFORCED_SIZE_TIME) {
count += 1;
} else {
break;
}
}
self.within_enforced_time = count;
}
pub fn cache_insert(&mut self, content: T) -> bool {
self.reset();
self.internal_insert(content)
}
fn internal_insert(&mut self, content: T) -> bool {
if self.within_enforced_time >= self.target {
false
} else {
let received_packet = ReceivedPacket {
content,
received: Instant::now(),
};
self.inner.push_back(received_packet);
self.within_enforced_time += 1;
true
}
}
}
impl<T> std::ops::Deref for ReceivedPacketCache<T> {
type Target = VecDeque<ReceivedPacket<T>>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T> std::ops::DerefMut for ReceivedPacketCache<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}