hopr_crypto_random/
lib.rs1use generic_array::{ArrayLength, GenericArray};
8use rand::CryptoRng;
9pub use rand::{Rng, RngCore};
10
11pub const MAX_RANDOM_INTEGER: u64 = 9007199254740991;
14
15#[cfg(all(debug_assertions, feature = "fixed-rng"))]
16use rand::SeedableRng;
17
18#[cfg(all(debug_assertions, feature = "fixed-rng"))]
19lazy_static::lazy_static! {
20 static ref FIXED_RNG: std::sync::Mutex<rand::rngs::StdRng> = std::sync::Mutex::new(rand::rngs::StdRng::from_seed([
21 0x5f, 0x57, 0xce, 0x2a, 0x84, 0x14, 0x7e, 0x88, 0x43, 0x56, 0x44, 0x56, 0x7f, 0x90, 0x4f, 0xb2, 0x04, 0x6b,
22 0x18, 0x42, 0x75, 0x69, 0xbe, 0x53, 0xb2, 0x29, 0x78, 0xbd, 0xf3, 0x0a, 0xda, 0xba,
23 ]));
24}
25
26#[cfg(all(debug_assertions, feature = "fixed-rng"))]
32#[inline]
33pub fn rng() -> impl RngCore + CryptoRng {
34 let mut global_rng = FIXED_RNG.lock().expect("failed to lock fixed RNG");
35 let mut seed = [0u8; 32];
36 global_rng.fill_bytes(&mut seed);
37
38 rand::rngs::StdRng::from_seed(seed)
39}
40
41#[cfg(any(not(debug_assertions), not(feature = "fixed-rng")))]
43#[inline]
44pub fn rng() -> impl RngCore + CryptoRng {
45 rand::rngs::OsRng
46}
47
48#[inline]
52pub const fn is_rng_fixed() -> bool {
53 cfg!(debug_assertions) && cfg!(feature = "fixed-rng")
54}
55
56#[inline]
58pub fn random_float() -> f64 {
59 rng().r#gen()
60}
61
62#[inline]
64pub fn random_float_in_range(range: std::ops::Range<f64>) -> f64 {
65 rng().gen_range(range)
66}
67
68pub fn random_integer(start: u64, end: Option<u64>) -> u64 {
72 let real_end = end.unwrap_or(MAX_RANDOM_INTEGER);
73
74 assert!(
75 real_end > start && real_end <= MAX_RANDOM_INTEGER,
76 "bounds must be 0 < {start} < {real_end} <= {MAX_RANDOM_INTEGER}"
77 );
78
79 let bound = real_end - start;
80 start + rng().gen_range(0..bound)
81}
82
83#[inline]
85pub fn random_fill(buffer: &mut [u8]) {
86 rng().fill_bytes(buffer);
87}
88
89pub fn random_bytes<const T: usize>() -> [u8; T] {
91 let mut ret = [0u8; T];
92 random_fill(&mut ret);
93 ret
94}
95
96pub fn random_array<L: ArrayLength>() -> GenericArray<u8, L> {
98 let mut ret = GenericArray::default();
99 random_fill(&mut ret);
100 ret
101}
102
103pub trait Randomizable {
105 fn random() -> Self;
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_random_integer() {
115 assert!(random_integer(10, None) > 10);
116
117 let bounded = random_integer(10, Some(20));
118 assert!((10..20).contains(&bounded));
119 }
120
121 #[test]
122 fn test_random_float() {
123 let f = random_float();
124 assert!((0.0..1.0).contains(&f));
125 }
126
127 #[test]
128 fn test_random_fill() {
129 let mut buffer = [0u8; 10];
130 random_fill(&mut buffer[2..9]);
132 assert_eq!(0, buffer[0]);
133 assert_eq!(0, buffer[1]);
134 assert_eq!(0, buffer[9]);
135 }
136}