use core::time::Duration;
use crate::error::BucketError;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BucketConfig {
capacity: u32,
refill_amount: u32,
refill_period: Duration,
initial: u32,
}
impl BucketConfig {
pub fn new(
capacity: u32,
refill_amount: u32,
refill_period: Duration,
initial: u32,
) -> Result<Self, BucketError> {
if capacity == 0 {
return Err(BucketError::ZeroCapacity);
}
if refill_amount == 0 {
return Err(BucketError::ZeroRefillAmount);
}
if refill_period.is_zero() {
return Err(BucketError::ZeroRefillPeriod);
}
Ok(Self {
capacity,
refill_amount,
refill_period,
initial: initial.min(capacity),
})
}
#[must_use]
pub const fn capacity(&self) -> u32 {
self.capacity
}
#[must_use]
pub const fn refill_amount(&self) -> u32 {
self.refill_amount
}
#[must_use]
pub const fn refill_period(&self) -> Duration {
self.refill_period
}
#[must_use]
pub const fn initial(&self) -> u32 {
self.initial
}
pub(crate) fn raw(
capacity: u32,
refill_amount: u32,
refill_period: Duration,
initial: u32,
) -> Self {
Self {
capacity,
refill_amount,
refill_period,
initial: initial.min(capacity),
}
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
use super::BucketConfig;
use crate::error::BucketError;
use core::time::Duration;
#[test]
fn test_new_accepts_valid_parameters() {
let config = BucketConfig::new(100, 50, Duration::from_secs(1), 25).unwrap();
assert_eq!(config.capacity(), 100);
assert_eq!(config.refill_amount(), 50);
assert_eq!(config.refill_period(), Duration::from_secs(1));
assert_eq!(config.initial(), 25);
}
#[test]
fn test_new_rejects_zero_capacity() {
let err = BucketConfig::new(0, 10, Duration::from_secs(1), 0).unwrap_err();
assert_eq!(err, BucketError::ZeroCapacity);
}
#[test]
fn test_new_rejects_zero_refill_amount() {
let err = BucketConfig::new(10, 0, Duration::from_secs(1), 0).unwrap_err();
assert_eq!(err, BucketError::ZeroRefillAmount);
}
#[test]
fn test_new_rejects_zero_refill_period() {
let err = BucketConfig::new(10, 10, Duration::ZERO, 0).unwrap_err();
assert_eq!(err, BucketError::ZeroRefillPeriod);
}
#[test]
fn test_new_clamps_initial_to_capacity() {
let config = BucketConfig::new(10, 10, Duration::from_secs(1), 999).unwrap();
assert_eq!(config.initial(), 10);
}
}