1use std::fs::File;
2use std::io::Read;
3
4pub fn fill_bytes(buf: &mut [u8]) {
7 if let Ok(mut f) = File::open("/dev/urandom")
8 && f.read_exact(buf).is_ok() {
9 return;
10 }
11
12 use std::time::SystemTime;
14 let mut seed = SystemTime::now()
15 .duration_since(SystemTime::UNIX_EPOCH)
16 .map(|d| d.as_nanos() as u64)
17 .unwrap_or(0xFEEDFACE_DEADC0DE);
18
19 for byte in buf.iter_mut() {
20 seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
21 *byte = (seed >> 56) as u8;
22 }
23}
24
25pub fn random_alphanumeric(length: usize) -> String {
27 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
28 let mut bytes = vec![0u8; length];
29 fill_bytes(&mut bytes);
30 let mut s = String::with_capacity(length);
31 for b in bytes {
32 let idx = (b as usize) % CHARS.len();
33 s.push(CHARS[idx] as char);
34 }
35 s
36}
37
38#[derive(Clone, Copy, Debug)]
40pub struct CustomRng;
41
42impl CustomRng {
43 pub fn fill_bytes(&self, buf: &mut [u8]) {
44 fill_bytes(buf);
45 }
46}
47
48pub fn rng() -> CustomRng {
49 CustomRng
50}
51
52pub mod distr {
53 pub struct Alphanumeric;
54
55 pub trait SampleString {
56 fn sample_string(&self, rng: &mut super::CustomRng, length: usize) -> String;
57 }
58
59 impl SampleString for Alphanumeric {
60 fn sample_string(&self, _rng: &mut super::CustomRng, length: usize) -> String {
61 super::random_alphanumeric(length)
62 }
63 }
64}