use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct InputRateTracker {
timestamps: Vec<Instant>,
window: Duration,
inputs_per_second: u32,
sustain_until: Instant,
sustain_duration: Duration,
}
impl Default for InputRateTracker {
fn default() -> Self {
Self {
timestamps: Vec::new(),
window: Duration::from_millis(100),
inputs_per_second: 60,
sustain_until: Instant::now(),
sustain_duration: Duration::from_secs(1),
}
}
}
impl InputRateTracker {
#[inline]
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) fn record_input(&mut self) {
let now = Instant::now();
self.timestamps.push(now);
self.prune_old_timestamps(now);
let min_events = self.inputs_per_second as u128 * self.window.as_millis() / 1000;
if self.timestamps.len() as u128 >= min_events {
self.sustain_until = now + self.sustain_duration;
}
}
#[inline]
pub(crate) fn is_high_rate(&self) -> bool {
Instant::now() < self.sustain_until
}
fn prune_old_timestamps(&mut self, now: Instant) {
self.timestamps
.retain(|&t| now.duration_since(t) <= self.window);
}
}