pagurus_game_std/
random.rs1use 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);