pub mod gcra;
pub mod leaky_bucket;
pub use self::gcra::*;
pub use self::leaky_bucket::*;
use {instant, InconsistentCapacity, NegativeMultiDecision};
use lib::*;
pub type DefaultAlgorithm = LeakyBucket;
pub trait NonConformance<P: instant::Relative = instant::TimeSource> {
fn earliest_possible(&self) -> P;
fn wait_time_from(&self, from: P) -> Duration {
let earliest = self.earliest_possible();
earliest.duration_since(earliest.min(from))
}
}
pub trait NonConformanceExt<P: instant::Absolute>: NonConformance<P> {
fn wait_time(&self) -> Duration {
self.wait_time_from(P::now())
}
}
impl<P: instant::Absolute, T> NonConformanceExt<P> for T where T: NonConformance<P> {}
pub trait Algorithm<P: instant::Relative = instant::TimeSource>:
Send + Sync + Sized + fmt::Debug
{
type BucketState: RateLimitState<Self, P>;
type NegativeDecision: PartialEq + fmt::Display + fmt::Debug + Send + Sync;
fn construct(
capacity: NonZeroU32,
cell_weight: NonZeroU32,
per_time_unit: Duration,
) -> Result<Self, InconsistentCapacity>;
fn test_n_and_update(
&self,
state: &Self::BucketState,
n: u32,
at: P,
) -> Result<(), NegativeMultiDecision<Self::NegativeDecision>>;
fn test_and_update(
&self,
state: &Self::BucketState,
at: P,
) -> Result<(), Self::NegativeDecision> {
match self.test_n_and_update(state, 1, at) {
Ok(()) => Ok(()),
Err(NegativeMultiDecision::BatchNonConforming(1, nc)) => Err(nc),
Err(other) => unreachable!(
"BUG: measuring a batch of size 1 reported insufficient capacity: {:?}",
other
),
}
}
}
pub trait RateLimitState<P, I: instant::Relative>: Default + Send + Sync + Eq + fmt::Debug {}
pub trait RateLimitStateWithClock<P, I: instant::Absolute>: RateLimitState<P, I> {
fn last_touched(&self, params: &P) -> I;
}
#[cfg(feature = "std")]
mod std {
use evmap::ShallowCopy;
use instant;
pub trait KeyableRateLimitState<P, I: instant::Absolute>:
super::RateLimitStateWithClock<P, I> + ShallowCopy
{
}
#[cfg(feature = "std")]
impl<T, P, I> KeyableRateLimitState<P, I> for T
where
T: super::RateLimitStateWithClock<P, I> + ShallowCopy,
I: instant::Absolute,
{
}
}
#[cfg(feature = "std")]
pub use self::std::*;