fakejpeg 0.2.0

Rust port of Alun Jones' fakejpeg library
Documentation
// SPDX-FileCopyrightText: Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: MIT

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);

// So this is a neat little trick here! Over on the generator side, we want to
// generate a lot of random numbers, and even use `Rng::fill_bytes()` to
// efficiently fill a buffer. But there's a catch: there are certain bytes we do
// **not** want to appear in the generate byte buffer!
//
// I used to mask those out byte by byte, but that felt - and was - inefficient.
// So I thought: what if we'd generate masked numbers in the first place? What
// if I wrapped whatever RNG is being used, and created my own RNG, derived from
// that, wrapping it, and applying the mask at the best possible time while
// still remaining generic: when generating 32 or 64 bit numbers.
//
// And that is precisely what MaskedRng does! Give it a type to wrap, and a
// mask, and it will do the masking behind the scenes, with much lower costs
// than byte-by-byte masking. No need for an iterator, no need to build another
// buffer (or mutate one): the random numbers leave the system masked.
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())
    }
}

// HOWEVER!
//
// The generator *also* wants to compute the size of the array it wants to fill,
// and *that* number should not be masked. So here's an implementation of
// `MaskedRng::random_range`, which calls the wrapped RNG directly, without
// masking the output.
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)
    }
}

// And finally: a small helper, so I can do stuff like:
//
// let mut masked_rng: MaskedRng<T, 0x6d6d_6d6d_6d6d_6d6d> = rng.into();
impl<T: Rng, const M: u64> From<T> for MaskedRng<T, M> {
    fn from(rng: T) -> Self {
        Self(rng)
    }
}