use std::collections::VecDeque;
use std::time::{Duration, Instant};
#[derive(Debug)]
pub(crate) struct RateLimit {
max: usize,
window: Duration,
events: VecDeque<Instant>,
}
impl RateLimit {
pub(crate) fn new(max: usize, window: Duration) -> Self {
Self {
max,
window,
events: VecDeque::new(),
}
}
pub(crate) fn allow(&mut self, now: Instant) -> bool {
while self
.events
.front()
.is_some_and(|event| now.duration_since(*event) >= self.window)
{
self.events.pop_front();
}
if self.events.len() >= self.max {
return false;
}
self.events.push_back(now);
true
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn allows_a_burst_then_waits_for_the_window() {
let window = Duration::from_secs(10);
let mut limit = RateLimit::new(3, window);
let start = Instant::now();
for _ in 0..3 {
assert!(limit.allow(start));
}
assert!(!limit.allow(start + window / 2));
assert!(limit.allow(start + window));
}
}