//! Throttle provider use std::iter; use std::num::NonZeroUsize; /// Buffer size for `DefaultBufferSize` pub const DEFAULT_BUFFER_SIZE: usize = 4096; /// `BufferProvider` that only provides the `DEFAULT_BUFFER_SIZE`. #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] pub struct DefaultBufferSize; /// `BufferProvider` that never provides a chunking buffer size. /// /// Therefore, buffers are always consumed as-is. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct NoBufferProvider; impl BufferProvider for NoBufferProvider { #[inline(always)] fn get_next_buffer_size(&mut self) -> Option { None } } impl BufferProvider for DefaultBufferSize { #[inline(always)] fn get_next_buffer_size(&mut self) -> Option { NonZeroUsize::new(DEFAULT_BUFFER_SIZE) } } /// The type that dictates the amount of time to wait between each read. pub type Duration = std::time::Duration; pub trait BufferProvider { /// Try to get the next buffer size. /// /// # Implementations /// * *Should* always return `Some` *at least* once with no upper bound on the number of `Some`s that can be returned. /// * *Should* return `Some` until there are no more left (*can* be infinite.) /// * After a `None`, there **must never** be another non-`None` value. fn get_next_buffer_size(&mut self) -> Option; } /// Iterator adaptor for `BufferProvider`'s `gen_next_buffer_size()`. #[derive(Debug, Clone)] pub struct BufferProviderIter(T); impl Iterator for BufferProviderIter { type Item = NonZeroUsize; #[inline] fn next(&mut self) -> Option { self.0.get_next_buffer_size() } } pub trait BufferProviderIterExt<'a> { type Iter: iter::Iterator + 'a; fn get_all_buffer_sizes(self) -> Self::Iter; } pub trait BufferProviderDynIterExt<'a> { fn gen_all_buffer_sizes(self: Box) -> Box +'a>; } impl<'a, T: BufferProvider + 'a> BufferProviderDynIterExt<'a> for T { #[inline] fn gen_all_buffer_sizes(self: Box) -> Box +'a> { Box::new(BufferProviderIter(*self)) } } impl<'a, T: BufferProvider + 'a> BufferProviderIterExt<'a> for T { type Iter = BufferProviderIter; #[inline(always)] fn get_all_buffer_sizes(self) -> Self::Iter { BufferProviderIter(self) } } impl BufferProvider for usize { #[inline(always)] fn get_next_buffer_size(&mut self) -> Option { NonZeroUsize::new(*self) } } impl BufferProvider for (usize, usize) { #[inline] fn get_next_buffer_size(&mut self) -> Option { use rand::prelude::*; NonZeroUsize::new(rand::thread_rng().gen_range(self.0..self.1)) } } pub trait DurationProvider { /// Try to get the next `Duration` from this provider. If there is not one available, `None` will be returned. /// /// # Implementations /// * *Should* always return `Some` *at least* once with no upper bound on the number of `Some`s that can be returned. /// * *Should* return `Some` until there are no more left (*can* be infinite.) /// * After a `None`, there **must never** be another non-`None` value. 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<'a> { fn get_timeout(&self) -> Box; } impl<'a, T: ?Sized> DynThrottleProvider<'a> for T where T: ThrottleProvider, T::Timer: 'a { #[inline(always)] fn get_timeout(&self) -> Box { Box::new(ThrottleProvider::get_timeout(&self)) } } impl<'a> DurationProvider for Box { #[inline(always)] fn get_next_duration(&mut self) -> Option { (**self).get_next_duration() } } impl<'a> ThrottleProvider for Box + 'a> { type Timer = Box; #[inline(always)] fn get_timeout(&self) -> Self::Timer { DynThrottleProvider::get_timeout(self) } } impl<'a> BufferProvider for Box { #[inline(always)] fn get_next_buffer_size(&mut self) -> Option { (**self).get_next_buffer_size() } } 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 buffer size adaptor that returns a buffer size from a uniformly-distributed `BufferProvider` range each time `get_next_buffer_size()` is called. #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] pub struct UniformBufferProvider>(R, std::marker::PhantomData); impl From for UniformBufferProvider where T: BufferProvider, R: std::ops::RangeBounds { #[inline(always)] fn from(from: R) -> Self { Self(from, std::marker::PhantomData) } } impl BufferProvider for UniformBufferProvider where T: BufferProvider + rand::distributions::uniform::SampleUniform, R: std::ops::RangeBounds+ rand::distributions::uniform::SampleRange, //for<'r> &'r R: , { #[inline] fn get_next_buffer_size(&mut self) -> Option { use rand::prelude::*; rand::thread_rng().gen_range(self.0.clone()).get_next_buffer_size() } } /// Provides a duration adaptor that returns a `Duration` from a uniformly-distributed `T` range each time `get_next_duration()` is called. #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] pub struct UniformDurationProvider>(R, std::marker::PhantomData); #[cfg(feature="none")] const _:() = { use rand::distributions::uniform::{ self, UniformSampler, SampleUniform, SampleRange, Uniform, }; use std::{ ops::{ RangeBounds, Bound, }, }; #[derive(Debug)] struct UniformDurationProviderSampler>(UniformDurationProvider); impl> UniformSampler for UniformDurationProviderSampler where R: SampleRange, T: SampleUniform, { type X = UniformDurationProvider; fn new_inclusive(low: B1, high: B2) -> Self where B1: uniform::SampleBorrow + Sized, B2: uniform::SampleBorrow + Sized { Self(::X::new_inclusive(low, high)) } fn sample(&self, rng: &mut Rng) -> Self::X { //use rand::prelude::*; //UniformDurationProvider(self.0.sample(rng)) todo!() } fn new(low: B1, high: B2) -> Self where B1: uniform::SampleBorrow + Sized, B2: uniform::SampleBorrow + Sized { ::new(low, high) } } }; #[cfg(feature="FUCK THIS")] const _:() = { use rand::distributions::uniform::{ self, UniformSampler, SampleUniform, SampleRange, Uniform, }; use std::{ ops::{ RangeBounds, Bound, }, marker::PhantomData }; use crate::ext::*; #[derive(Debug, Clone, Copy)] struct UDPSampler(uniform::UniformDuration, PhantomData); impl UniformSampler for UDPSampler where D: RangeBounds { type X = UniformDurationProvider; fn new_inclusive(low: B1, high: B2) -> Self where B1: uniform::SampleBorrow + Sized, B2: uniform::SampleBorrow + Sized { Self(uniform::UniformDuration::new_inclusive(low.borrow().0.start_bound(), high.borrow().0.end_bound()), PhantomData) } fn sample(&self, rng: &mut R) -> Self::X { todo!() } fn new(low: B1, high: B2) -> Self where B1: uniform::SampleBorrow + Sized, B2: uniform::SampleBorrow + Sized { Self(uniform::UniformDuration::new(low, high), PhantomData) } } impl SampleUniform for UniformDurationProvider where R: RangeBounds + SampleRange { type Sampler = UDPSampler; } }; impl rand::distributions::uniform::SampleRange for UniformDurationProvider where R: std::ops::RangeBounds + rand::distributions::uniform::SampleRange, T: rand::distributions::uniform::SampleUniform { #[inline(always)] fn sample_single(self, rng: &mut Rng) -> T { self.0.sample_single(rng) } #[inline] fn is_empty(&self) -> bool { use super::ext::*; self.0.start_bound().map_impl(into_addr) == self.0.end_bound().map_impl(into_addr) } } impl From for UniformDurationProvider where T: DurationProvider, R: std::ops::RangeBounds { #[inline(always)] fn from(from: R) -> Self { Self(from, std::marker::PhantomData) } } impl DurationProvider for UniformDurationProvider where T: DurationProvider + rand::distributions::uniform::SampleUniform, R: std::ops::RangeBounds+ rand::distributions::uniform::SampleRange, //for<'r> &'r R: rand::distributions::uniform::SampleRange { #[inline] fn get_next_duration(&mut self) -> Option { use rand::prelude::*; rand::thread_rng().gen_range(self.0.clone()).get_next_duration() } } /// 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); /// Provides a single `DurationProvider` on each call to `get_timeout()`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SingleThrottleProvider(D); impl From for SingleThrottleProvider { #[inline(always)] fn from(from: D) -> Self { Self(from) } } /// Always provides no timeout duration. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct NoThrottleProvider; /// Never provides a timeout duration #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct NoDurationProvider; impl DurationProvider for NoDurationProvider { #[inline(always)] fn get_next_duration(&mut self) -> Option { None } } impl ThrottleProvider for NoThrottleProvider { type Timer = NoDurationProvider; #[inline(always)] fn get_timeout(&self) -> Self::Timer { NoDurationProvider } } impl ThrottleProvider for SingleThrottleProvider { type Timer = D; #[inline(always)] fn get_timeout(&self) -> Self::Timer { self.0.clone() } } /*impl From for SingleThrottleProvider { #[inline(always)] fn from(from: Duration) -> Self { Self(from) } }*/ //TODO: Split this into multiple: From: same. // And From,From<..{,=}x>: x..BUFFER_MAX_LEN, 0..{,=}x // (seperate impls needed for type signature. which is annoying...) // // XXX: Alternatively, we could add `new_from_range(range: R2)` methods for UniformThrottleProvider<_, R> where R determines which we use. This is probably the better way of doing it. 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 + rand::distributions::uniform::SampleRange, //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.clone()) } } pub mod prelude { pub use super::{ ThrottleProvider, DynThrottleProvider, Duration, DurationProvider, BufferProvider, DurationProviderExt as _, DurationProviderIterExt as _, BufferProviderIterExt as _, BufferProviderDynIterExt as _, DurationProviderIter, BufferProviderIter, UniformDurationProvider, UniformThrottleProvider, UniformBufferProvider, SingleThrottleProvider, DefaultBufferSize, NoThrottleProvider, NoDurationProvider, NoBufferProvider, }; }