use std::{
collections::HashMap,
iter::Inspect,
time::{Duration, Instant},
};
use crate::{FixedBucket, Selfb};
impl FixedBucket {
pub fn new(total_request: u64, minutes: u64) -> Self {
FixedBucket {
request: total_request,
duration: Duration::from_secs(minutes * 60),
capacity: 0,
rates: 0.0,
last_update: HashMap::new(),
requests: HashMap::new(),
}
}
pub fn bucket(self, capacity: u64, rates: f64) -> Self {
let rates = rates / 1000.0;
FixedBucket {
request: self.request,
duration: self.duration,
capacity: capacity,
rates: rates,
last_update: self.last_update,
requests: self.requests,
}
}
fn bucket_update(&mut self, key: String) {
let now = Instant::now();
let (tokens, b) = self.last_update.entry(key).or_insert((0.0, now));
println!("{}", tokens);
let current_time = now.duration_since(*b).as_millis();
let token = (self.rates * current_time as f64).ceil();
*tokens = (*tokens + token).min(self.capacity as f64);
*b = now;
}
fn fixed_bucket(&mut self, key: String) -> bool {
let now = Instant::now();
let (tokens, b) = self.requests.entry(key).or_insert((0, now));
let current = now.duration_since(*b);
if current > self.duration {
*b = now;
*tokens = 0;
}
if *tokens <= self.request {
*tokens += 1;
true
} else {
false
}
}
pub fn allow(&mut self, ip: impl Into<String> + Copy, token: f64) -> Selfb {
let ip = ip.into();
let request = self.fixed_bucket(ip.clone());
if request {
self.bucket_update(ip.clone());
let (tokens, _) = self.last_update.get_mut(&ip).unwrap();
if *tokens >= token {
*tokens -= token;
Selfb {
is_allowed: true,
remaning_count: *tokens as u64,
}
} else {
Selfb {
is_allowed: false,
remaning_count: *tokens as u64,
}
}
} else {
Selfb {
is_allowed: false,
remaning_count: 0,
}
}
}
}