use std::{
iter::FusedIterator,
ops::{Range, RangeInclusive},
};
use anyhow::Result;
use rand::Rng;
mod standard_buffered;
pub use standard_buffered::StandardBuffered;
mod utils;
pub trait TryDistribution<T> {
fn try_sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Result<T>;
fn sample_iter<R>(self, rng: R) -> TryDistIter<Self, R, T>
where
R: Rng,
Self: Sized,
{
TryDistIter {
distr: self,
rng,
phantom: ::core::marker::PhantomData,
}
}
fn map<F, S>(self, func: F) -> TryDistMap<Self, F, T, S>
where
F: Fn(T) -> S,
Self: Sized,
{
TryDistMap {
distr: self,
func,
phantom: ::core::marker::PhantomData,
}
}
}
#[derive(Debug)]
pub struct TryDistIter<D, R, T> {
distr: D,
rng: R,
phantom: ::core::marker::PhantomData<T>,
}
impl<D, R, T> Iterator for TryDistIter<D, R, T>
where
D: TryDistribution<T>,
R: Rng,
{
type Item = T;
#[inline(always)]
fn next(&mut self) -> Option<T> {
self.distr.try_sample(&mut self.rng).ok()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::max_value(), None)
}
}
impl<D, R, T> FusedIterator for TryDistIter<D, R, T>
where
D: TryDistribution<T>,
R: Rng,
{
}
#[cfg(features = "nightly")]
impl<D, R, T> iter::TrustedLen for TryDistIter<D, R, T>
where
D: TryDistribution<T>,
R: Rng,
{
}
#[derive(Debug)]
pub struct TryDistMap<D, F, T, S> {
distr: D,
func: F,
phantom: ::core::marker::PhantomData<fn(T) -> S>,
}
impl<D, F, T, S> TryDistribution<S> for TryDistMap<D, F, T, S>
where
D: TryDistribution<T>,
F: Fn(T) -> Result<S>,
{
fn try_sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Result<S> {
(self.func)(self.distr.try_sample(rng)?)
}
}
pub trait Buffered {
fn try_ensure<R: Rng + ?Sized>(&self, bits: usize, rng: &mut R) -> Result<()>;
fn ensure<R: Rng + ?Sized>(&self, bits: usize, rng: &mut R);
}
pub trait Ranged<T> {
fn sample_range<R: Rng + ?Sized>(&self, rng: &mut R, range: Range<T>) -> T;
fn sample_range_inclusive<R: Rng + ?Sized>(&self, rng: &mut R, range: RangeInclusive<T>) -> T;
}
pub trait TryRanged<T> {
fn try_sample_range<R: Rng + ?Sized>(&self, rng: &mut R, range: Range<T>) -> Result<T>;
fn try_sample_range_inclusive<R: Rng + ?Sized>(
&self,
rng: &mut R,
range: RangeInclusive<T>,
) -> Result<T>;
}
pub trait BitsNeeded<T> {
fn bits_needed(&self, value: T) -> usize;
}