1use std::fmt;
2
3#[derive(Debug)]
4pub enum RngError {
5 SystemTimeError(std::time::SystemTimeError),
6 EnvVarMissing(String),
7 EnvVarParseError {
8 var_name: String,
9 var_value: String,
10 error: <u32 as std::str::FromStr>::Err,
11 },
12}
13
14impl fmt::Display for RngError {
15 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16 write!(f, "{:?}", self)
17 }
18}
19
20impl std::error::Error for RngError {}
21
22pub struct Rng(u32);
25
26impl Rng {
27 pub fn new(seed: u32) -> Rng {
29 Rng(seed)
30 }
31
32 pub fn new_from_time() -> Result<Rng, RngError> {
34 std::time::SystemTime::now()
35 .duration_since(std::time::UNIX_EPOCH)
36 .map(|d| Rng(d.subsec_millis()))
37 .map_err(RngError::SystemTimeError)
38 }
39
40 pub fn new_from_env_var(var_name: &str) -> Result<Rng, RngError> {
42 let value = std::env::vars()
43 .find_map(|(key, value)| if key == var_name { Some(value) } else { None })
44 .ok_or_else(|| RngError::EnvVarMissing(var_name.into()))?;
45 value
46 .parse::<u32>()
47 .map(Rng)
48 .map_err(|error| RngError::EnvVarParseError {
49 var_name: var_name.into(),
50 var_value: value,
51 error,
52 })
53 }
54
55 pub fn u32(&mut self) -> u32 {
65 let mut x = self.0;
66 x ^= x << 13;
67 x ^= x >> 17;
68 x ^= x << 5;
69 self.0 = x;
70 x
71 }
72}