pagurus_game_std/
random.rs

1use rand_chacha::ChaChaRng;
2use rand_core::{RngCore, SeedableRng as _};
3use std::{num::NonZeroU32, time::Duration};
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
6pub struct StdRngState {
7    pub seed: [u8; 32],
8    pub word_pos: u128,
9}
10
11#[derive(Debug)]
12pub struct StdRng {
13    inner: ChaChaRng,
14}
15
16impl StdRng {
17    pub fn from_clock_seed(now: Duration) -> Self {
18        let inner = ChaChaRng::seed_from_u64(now.as_micros() as u64);
19        Self { inner }
20    }
21
22    pub fn from_state(state: StdRngState) -> Self {
23        let mut inner = ChaChaRng::from_seed(state.seed);
24        inner.set_word_pos(state.word_pos);
25        Self { inner }
26    }
27
28    pub fn state(&self) -> StdRngState {
29        StdRngState {
30            seed: self.inner.get_seed(),
31            word_pos: self.inner.get_word_pos(),
32        }
33    }
34}
35
36impl Default for StdRng {
37    fn default() -> Self {
38        Self::from_clock_seed(Duration::from_secs(0))
39    }
40}
41
42impl RngCore for StdRng {
43    fn next_u32(&mut self) -> u32 {
44        self.inner.next_u32()
45    }
46
47    fn next_u64(&mut self) -> u64 {
48        self.inner.next_u64()
49    }
50
51    fn fill_bytes(&mut self, dest: &mut [u8]) {
52        self.inner.fill_bytes(dest);
53    }
54
55    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
56        self.inner.try_fill_bytes(dest)
57    }
58}
59
60fn always_fail(_buf: &mut [u8]) -> Result<(), getrandom::Error> {
61    let custom_code = getrandom::Error::CUSTOM_START + 7397;
62    Err(NonZeroU32::new(custom_code).expect("unreachable").into())
63}
64
65getrandom::register_custom_getrandom!(always_fail);