use std::time::Instant;
pub struct TokenBucket {
rate: f64, capacity: f64, tokens: f64, last: Instant, packet_size: f64, }
impl TokenBucket {
pub fn new(bits_per_second: u64, burst_bytes: u64, packet_size: u16) -> Self {
let rate = bits_per_second as f64 / 8.0;
let capacity = burst_bytes as f64;
Self {
rate,
capacity,
tokens: packet_size as f64, last: Instant::now(),
packet_size: packet_size as f64,
}
}
pub fn wait_for_capacity(&mut self) {
self.refill();
if self.tokens < self.packet_size {
let deficit = self.packet_size - self.tokens;
let wait = std::time::Duration::from_secs_f64(deficit / self.rate);
std::thread::sleep(wait);
self.refill();
}
}
pub fn consume(&mut self, size: usize) {
self.tokens -= size as f64;
}
fn refill(&mut self) {
let now = Instant::now();
let elapsed = now.duration_since(self.last).as_secs_f64();
self.tokens = (self.tokens + elapsed * self.rate).min(self.capacity);
self.last = now;
}
}