//! Throttle provider use std::time::Duration; use std::iter; pub trait DurationProvider { fn get_next_duration(&mut self) -> Option; } /// An iterator adaptor for a `DurationProvider`. #[derive(Debug, Clone)] pub struct DurationProviderIter(T); impl DurationProviderIter { /// Consume into the backing `DurationProvider` #[inline(always)] pub fn into_inner(self) -> T { self.0 } } impl Iterator for DurationProviderIter { type Item = Duration; #[inline(always)] fn next(&mut self) -> Option { self.0.get_next_duration() } } pub trait DurationProviderIterExt<'a> { type Iter: iter::Iterator + 'a; fn get_all_durations(self) -> Self::Iter; } pub trait DurationProviderExt<'a> { fn get_all_durations_dyn(self: Box) -> Box + 'a>; } impl<'a, T: DurationProvider + 'a> DurationProviderIterExt<'a> for T { type Iter = DurationProviderIter; #[inline(always)] fn get_all_durations(self) -> Self::Iter { DurationProviderIter(self) } } impl<'a, T: ?Sized + DurationProvider + 'a> DurationProviderExt<'a> for T { #[inline] fn get_all_durations_dyn(self: Box) -> Box + 'a> { #[derive(Debug)] struct Iter(Box); impl Iterator for Iter { type Item = Duration; fn next(&mut self) -> Option { self.0.get_next_duration() } } Box::new(Iter(self)) } } impl DurationProvider for Duration { #[inline(always)] fn get_next_duration(&mut self) -> Option { Some(*self) } } pub trait ThrottleProvider { type Timer: DurationProvider; fn get_timeout(&self) -> Self::Timer; } pub trait DynThrottleProvider { fn get_timeout(&self) -> Box; } impl DynThrottleProvider for T where T: ThrottleProvider { #[inline(always)] fn get_timeout(&self) -> Box { Box::new(ThrottleProvider::get_timeout(&self)) } } impl<'a, T: ?Sized> ThrottleProvider for &'a T where T: ThrottleProvider { type Timer = T::Timer; #[inline(always)] fn get_timeout(&self) -> Self::Timer { T::get_timeout(self) } } impl ThrottleProvider for Duration { type Timer = Self; fn get_timeout(&self) -> Self::Timer { self.clone() } } /// Provides a throttle adaptor that returns a uniformly-distributed `T` each time `get_timeout()` is called. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UniformThrottleProvider>(R, std::marker::PhantomData); impl From for UniformThrottleProvider where T: DurationProvider, R: std::ops::RangeBounds { #[inline(always)] fn from(from: R) -> Self { Self(from, std::marker::PhantomData) } } impl ThrottleProvider for UniformThrottleProvider where T: DurationProvider + rand::distributions::uniform::SampleUniform, R: std::ops::RangeBounds, for <'r> &'r R: rand::distributions::uniform::SampleRange, { type Timer = T; #[inline] fn get_timeout(&self) -> Self::Timer { use rand::prelude::*; rand::thread_rng().gen_range(&self.0) } }