use std::time::{Duration, Instant};
use std::convert::TryInto;
+/// Rate limiter interface.
+pub trait RateLimit {
+ /// Update rate and bucket size
+ fn update_rate(&mut self, rate: u64, bucket_size: u64);
+
+ /// Returns the average rate (since `start_time`)
+ fn average_rate(&self, current_time: Instant) -> f64;
+
+ /// Register traffic, returning a proposed delay to reach the
+ /// expected rate.
+ fn register_traffic(&mut self, current_time: Instant, data_len: u64) -> Duration;
+}
+
/// Token bucket based rate limiter
pub struct RateLimiter {
rate: u64, // tokens/second
}
}
- /// Update rate and bucket size
- pub fn update_rate(&mut self, rate: u64, bucket_size: u64) {
- self.rate = rate;
-
- if bucket_size < self.bucket_size && self.consumed_tokens > bucket_size {
- self.consumed_tokens = bucket_size; // start again
- }
-
- self.bucket_size = bucket_size;
- }
-
- /// Returns the average rate (since `start_time`)
- pub fn average_rate(&self, current_time: Instant) -> f64 {
- let time_diff = current_time.saturating_duration_since(self.start_time).as_secs_f64();
- if time_diff <= 0.0 {
- 0.0
- } else {
- (self.traffic as f64) / time_diff
- }
- }
-
fn refill_bucket(&mut self, current_time: Instant) {
let time_diff = match current_time.checked_duration_since(self.last_update) {
Some(duration) => duration.as_nanos(),
self.consumed_tokens = self.consumed_tokens.saturating_sub(allowed_traffic);
}
+}
+
+impl RateLimit for RateLimiter {
+
+ fn update_rate(&mut self, rate: u64, bucket_size: u64) {
+ self.rate = rate;
+
+ if bucket_size < self.bucket_size && self.consumed_tokens > bucket_size {
+ self.consumed_tokens = bucket_size; // start again
+ }
+
+ self.bucket_size = bucket_size;
+ }
+
+ fn average_rate(&self, current_time: Instant) -> f64 {
+ let time_diff = current_time.saturating_duration_since(self.start_time).as_secs_f64();
+ if time_diff <= 0.0 {
+ 0.0
+ } else {
+ (self.traffic as f64) / time_diff
+ }
+ }
- /// Register traffic, returning a proposed delay to reach the expected rate.
- pub fn register_traffic(&mut self, current_time: Instant, data_len: u64) -> Duration {
+ fn register_traffic(&mut self, current_time: Instant, data_len: u64) -> Duration {
self.refill_bucket(current_time);
self.traffic += data_len;