#![no_std]
use core::convert::Infallible;
use blake3::{Hasher, OutputReader};
use rand_core::{
block::BlockRngCore,
impls::{next_u32_via_fill, next_u64_via_fill},
CryptoRng, Error, RngCore, SeedableRng,
};
use load_buffer::{BufferedLoader, Load};
struct LoadOutputReader {
reader: OutputReader,
}
impl From<OutputReader> for LoadOutputReader {
fn from(reader: OutputReader) -> Self {
Self { reader }
}
}
impl From<Hasher> for LoadOutputReader {
fn from(hasher: Hasher) -> Self {
Self {
reader: hasher.finalize_xof(),
}
}
}
impl Load for LoadOutputReader {
type Error = Infallible;
fn load(&mut self, destination: &mut [u8]) -> Result<(), Self::Error> {
self.reader.fill(destination);
Ok(())
}
}
pub struct Rng {
loader: BufferedLoader<[u8; 64], LoadOutputReader>,
}
impl From<OutputReader> for Rng {
fn from(reader: OutputReader) -> Self {
let loader = BufferedLoader::new_static(LoadOutputReader::from(reader));
Self { loader }
}
}
impl From<Hasher> for Rng {
fn from(hasher: Hasher) -> Self {
let loader = BufferedLoader::new_static(LoadOutputReader::from(hasher));
Self { loader }
}
}
impl SeedableRng for Rng {
type Seed = [u8; 32];
#[inline]
fn from_seed(seed: Self::Seed) -> Self {
Hasher::new_keyed(&seed).finalize_xof().into()
}
}
impl RngCore for Rng {
#[inline]
fn next_u32(&mut self) -> u32 {
next_u32_via_fill(self)
}
#[inline]
fn next_u64(&mut self) -> u64 {
next_u64_via_fill(self)
}
#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.loader.load(dest).unwrap();
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
self.loader.load(dest).unwrap();
Ok(())
}
}
const BLOCK_COUNT: usize = 16;
impl BlockRngCore for Rng {
type Item = u32;
type Results = [u32; BLOCK_COUNT];
fn generate(&mut self, results: &mut Self::Results) {
let mut buf = [0u8; BLOCK_COUNT * 4];
self.loader.load(&mut buf).unwrap();
for (dest, src) in results.iter_mut().zip(buf.chunks_exact(4)) {
*dest = u32::from_le_bytes(src.try_into().unwrap());
}
}
}
impl CryptoRng for Rng {}
pub struct UnbufferedRng {
loader: LoadOutputReader,
}
impl From<OutputReader> for UnbufferedRng {
fn from(reader: OutputReader) -> Self {
let loader = LoadOutputReader::from(reader);
Self { loader }
}
}
impl From<Hasher> for UnbufferedRng {
fn from(hasher: Hasher) -> Self {
let loader = LoadOutputReader::from(hasher);
Self { loader }
}
}
impl SeedableRng for UnbufferedRng {
type Seed = [u8; 32];
#[inline]
fn from_seed(seed: Self::Seed) -> Self {
Hasher::new_keyed(&seed).finalize_xof().into()
}
}
impl RngCore for UnbufferedRng {
#[inline]
fn next_u32(&mut self) -> u32 {
next_u32_via_fill(self)
}
#[inline]
fn next_u64(&mut self) -> u64 {
next_u64_via_fill(self)
}
#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.loader.load(dest).unwrap();
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
self.loader.load(dest).unwrap();
Ok(())
}
}
impl BlockRngCore for UnbufferedRng {
type Item = u32;
type Results = [u32; BLOCK_COUNT];
fn generate(&mut self, results: &mut Self::Results) {
let mut buf = [0u8; BLOCK_COUNT * 4];
self.loader.load(&mut buf).unwrap();
for (dest, src) in results.iter_mut().zip(buf.chunks_exact(4)) {
*dest = u32::from_le_bytes(src.try_into().unwrap());
}
}
}
impl CryptoRng for UnbufferedRng {}
#[cfg(test)]
mod test {
use super::*;
use rand::rngs::adapter::ReseedingRng;
use rand::rngs::OsRng;
use rand::Rng as _;
#[test]
fn test_rand_core() {
let mut seeded = crate::Rng::from_seed(*b"0123456789abcdefghijklmnopqrstuv");
let mut buf = [0u8; 64];
seeded.fill_bytes(&mut buf);
assert_eq!(
&buf,
b"\
\x57\x63\x36\x95\x85\xc5\x58\x99\x4a\x3e\xe0\x27\x78\x87\x94\x1f\
\xf0\xf8\xbd\x3a\xca\x96\xfa\x00\xdb\xb8\x25\x07\x2c\x47\x67\xf1\
\x69\xd0\xf2\x11\x68\xff\x75\x74\x4c\x1c\x48\x8f\xee\x7a\x01\x78\
\x52\xcf\x04\x5d\xc2\x9e\xa1\x0e\x09\x63\x76\x18\xc3\x5f\xf6\x10\
",
);
assert_eq!(seeded.gen::<u32>(), 0xc6a18732);
assert_eq!(seeded.gen::<u64>(), 0x705c00977b0d7be0);
let mut seeded = crate::Rng::from_seed(*b"0123456789abcdefghijklmnopqrstuv");
let mut buf = [0u8; 63];
seeded.fill_bytes(&mut buf);
assert_eq!(
&buf,
b"\
\x57\x63\x36\x95\x85\xc5\x58\x99\x4a\x3e\xe0\x27\x78\x87\x94\x1f\
\xf0\xf8\xbd\x3a\xca\x96\xfa\x00\xdb\xb8\x25\x07\x2c\x47\x67\xf1\
\x69\xd0\xf2\x11\x68\xff\x75\x74\x4c\x1c\x48\x8f\xee\x7a\x01\x78\
\x52\xcf\x04\x5d\xc2\x9e\xa1\x0e\x09\x63\x76\x18\xc3\x5f\xf6\
",
);
assert_eq!(seeded.gen::<u32>(), 0xa1873210);
assert_eq!(seeded.gen::<u64>(), 0x5c00977b0d7be0c6);
}
#[test]
fn test_reseeding_rng() {
let mut reseeding = ReseedingRng::new(Rng::from_rng(OsRng).unwrap(), 1024 * 256, OsRng);
let _out: u32 = reseeding.gen();
}
}