diff --git a/src/ext.rs b/src/ext.rs new file mode 100644 index 0000000..79ccfd8 --- /dev/null +++ b/src/ext.rs @@ -0,0 +1,37 @@ +//! Extension +use std::ops::{ + RangeBounds, + Bound +}; +pub trait BoundExt +{ + fn map_impl(self, f: F) -> Bound + where F: FnOnce(T) -> U; +} + +impl BoundExt for Bound +{ + #[inline(always)] + fn map_impl(self, f: F) -> Bound + where F: FnOnce(T) -> U { + //! Copied from stdlib + use Bound::*; + match self { + Unbounded => Unbounded, + Included(x) => Included(f(x)), + Excluded(x) => Excluded(f(x)), + } + } +} + +#[inline(always)] pub fn erase(_: T) -> () {} + +/// Get the memory address this reference points to. +/// +/// # Note +/// If `T` is a fat pointer, it is cast to a thin-pointer first. +#[inline(always)] +pub fn into_addr(r: &T) -> usize +{ + r as *const T as *const std::convert::Infallible as usize +} diff --git a/src/main.rs b/src/main.rs index 0fe39f6..bd43a77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,27 @@ use std::io; +mod ext; use ext::*; + mod conf; mod prov; mod stream; fn main() -> io::Result<()> { let mut input = io::stdin().lock(); - let mut output = stream::ThrottleAdaptor::new(prov::UniformThrottleProvider::from(prov::Duration::from_millis(5)..prov::Duration::from_millis(50)), prov::UniformBufferProvider::from(0usize..=10), io::stdout().lock()); + let mut output = stream::ThrottleAdaptor + /*::new(prov::UniformThrottleProvider::from( + prov::UniformDurationProvider::from( + prov::Duration::from_millis(5) + ..prov::Duration::from_millis(50) +) + ..prov::UniformDurationProvider::from( + prov::Duration::from_millis(10) + ..prov::Duration::from_millis(100) +))*/ //TODO: Figure out how to fucking implement that god-damn uniform sampler for `UniformDurationProvider`. Ugh... + ::new( prov::SingleThrottleProvider::from(prov::UniformDurationProvider::from(prov::Duration::from_millis(5)..prov::Duration::from_millis(10))) + , prov::UniformBufferProvider::from(0usize..=20) + , io::stdout().lock()); + let copied = io::copy(&mut input, &mut output)?; if cfg!(debug_assertions) { eprintln!("Copied {copied} bytes from input -{output:?}> output"); diff --git a/src/prov.rs b/src/prov.rs index 7719710..b43aaf3 100644 --- a/src/prov.rs +++ b/src/prov.rs @@ -286,6 +286,116 @@ where T: BufferProvider + rand::distributions::uniform::SampleUniform, #[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 @@ -316,7 +426,18 @@ pub struct UniformThrottleProvider>(R, st /// Provides a single `DurationProvider` on each call to `get_timeout()`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct SingleThrottleProvider(D); +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)] @@ -352,16 +473,21 @@ impl ThrottleProvider for SingleThrottleProvider } } -impl From for SingleThrottleProvider +/*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