1use crate::rng::*;
2use chachacha::*;
3use core::mem::MaybeUninit;
4use getrandom::fill;
5
6pub struct SecureRng {
12 index: usize,
13 buf: [u64; BUF_LEN_U64],
14 internal: ChaCha8Djb,
15}
16
17impl SecureYARandGenerator for SecureRng {
18 #[inline]
19 fn fill_bytes(&mut self, dst: &mut [u8]) {
20 self.internal.fill(dst);
23 }
24}
25
26impl YARandGenerator for SecureRng {
27 #[inline]
28 fn try_new() -> Result<Self, getrandom::Error> {
29 #[allow(invalid_value)]
33 let mut state = unsafe { MaybeUninit::<[u8; SEED_LEN_U8]>::uninit().assume_init() };
34 fill(&mut state)?;
35 let mut internal = ChaCha8Djb::from(state);
36 let buf = internal.get_block_u64();
37 let index = 0;
38 Ok(SecureRng {
39 index,
40 buf,
41 internal,
42 })
43 }
44
45 #[cfg_attr(feature = "inline", inline)]
46 fn u64(&mut self) -> u64 {
47 if self.index >= self.buf.len() {
48 self.internal.fill_block_u64(&mut self.buf);
49 self.index = 0;
50 }
51 let result = self.buf[self.index];
52 self.index += 1;
53 result
54 }
55}