use rand::{
Rng, RngExt, TryRng,
distr::uniform::{SampleRange, SampleUniform},
rand_core::utils::fill_bytes_via_next_word,
};
pub struct MaskedRng<T: TryRng, const M: u64>(T);
impl<T: TryRng, const M: u64> TryRng for MaskedRng<T, M> {
type Error = T::Error;
#[inline]
#[allow(clippy::cast_possible_truncation)]
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(self.0.try_next_u32()? & (M as u32))
}
#[inline]
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok(self.0.try_next_u64()? & M)
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
fill_bytes_via_next_word(dest, || self.try_next_u64())
}
}
impl<T: Rng, const M: u64> MaskedRng<T, M> {
pub fn random_range<O, R>(&mut self, range: R) -> O
where
O: SampleUniform,
R: SampleRange<O>,
{
self.0.random_range(range)
}
}
impl<T: Rng, const M: u64> From<T> for MaskedRng<T, M> {
fn from(rng: T) -> Self {
Self(rng)
}
}