1use std::cell::RefCell;
6use std::rc::Rc;
7use std::sync::Mutex;
8
9use log::trace;
10use malloc_size_of_derive::MallocSizeOf;
11use rand::distributions::{Distribution, Standard};
21use rand::rngs::OsRng;
22use rand::rngs::adapter::ReseedingRng;
23pub use rand::seq::SliceRandom;
24pub use rand::{Rng, RngCore, SeedableRng};
25use rand_isaac::isaac::IsaacCore;
26use uuid::{Builder, Uuid};
27
28static OS_RNG: Mutex<OsRng> = Mutex::new(OsRng);
30
31const RESEED_THRESHOLD: u64 = 32_768;
33
34#[derive(MallocSizeOf)]
36pub struct ServoRng {
37 #[ignore_malloc_size_of = "Defined in rand"]
38 rng: ReseedingRng<IsaacCore, ServoReseeder>,
39}
40
41impl RngCore for ServoRng {
42 #[inline]
43 fn next_u32(&mut self) -> u32 {
44 self.rng.next_u32()
45 }
46
47 #[inline]
48 fn next_u64(&mut self) -> u64 {
49 self.rng.next_u64()
50 }
51
52 #[inline]
53 fn fill_bytes(&mut self, bytes: &mut [u8]) {
54 self.rng.fill_bytes(bytes)
55 }
56
57 fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> std::result::Result<(), rand_core::Error> {
58 self.rng.try_fill_bytes(bytes)
59 }
60}
61
62#[derive(Default)]
63pub struct Seed([u8; 32]);
64
65impl AsMut<[u8]> for Seed {
66 fn as_mut(&mut self) -> &mut [u8] {
67 &mut self.0
68 }
69}
70
71impl SeedableRng for ServoRng {
72 type Seed = Seed;
73
74 fn from_seed(seed: Seed) -> ServoRng {
77 trace!("Creating a new ServoRng.");
78 let isaac_rng = IsaacCore::from_seed(seed.0);
79 let reseeding_rng = ReseedingRng::new(isaac_rng, RESEED_THRESHOLD, ServoReseeder);
80 ServoRng { rng: reseeding_rng }
81 }
82}
83
84impl ServoRng {
85 pub fn new_manually_reseeded(seed: u64) -> ServoRng {
90 trace!("Creating a new manually-reseeded ServoRng.");
91 let isaac_rng = IsaacCore::seed_from_u64(seed);
92 let reseeding_rng = ReseedingRng::new(isaac_rng, 0, ServoReseeder);
93 ServoRng { rng: reseeding_rng }
94 }
95}
96
97impl Default for ServoRng {
98 fn default() -> Self {
103 trace!("Creating new ServoRng.");
104 let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
105 let isaac_rng = IsaacCore::from_rng(&mut *os_rng).unwrap();
106 let reseeding_rng = ReseedingRng::new(isaac_rng, RESEED_THRESHOLD, ServoReseeder);
107 ServoRng { rng: reseeding_rng }
108 }
109}
110
111struct ServoReseeder;
113
114impl RngCore for ServoReseeder {
115 #[inline]
116 fn next_u32(&mut self) -> u32 {
117 let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
118 os_rng.next_u32()
119 }
120
121 #[inline]
122 fn next_u64(&mut self) -> u64 {
123 let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
124 os_rng.next_u64()
125 }
126
127 #[inline]
128 fn fill_bytes(&mut self, bytes: &mut [u8]) {
129 let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
130 os_rng.fill_bytes(bytes)
131 }
132
133 #[inline]
134 fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> std::result::Result<(), rand_core::Error> {
135 let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
136 os_rng.try_fill_bytes(bytes)
137 }
138}
139
140impl Default for ServoReseeder {
141 fn default() -> ServoReseeder {
142 ServoReseeder
143 }
144}
145
146#[derive(Clone)]
148pub struct ServoThreadRng {
149 rng: Rc<RefCell<ServoRng>>,
150}
151
152pub fn thread_rng() -> ServoThreadRng {
154 SERVO_THREAD_RNG.with(|t| t.clone())
155}
156
157thread_local! {
158 static SERVO_THREAD_RNG: ServoThreadRng = ServoThreadRng { rng: Rc::new(RefCell::new(ServoRng::default())) };
159}
160
161impl RngCore for ServoThreadRng {
162 fn next_u32(&mut self) -> u32 {
163 self.rng.borrow_mut().next_u32()
164 }
165
166 fn next_u64(&mut self) -> u64 {
167 self.rng.borrow_mut().next_u64()
168 }
169
170 #[inline]
171 fn fill_bytes(&mut self, bytes: &mut [u8]) {
172 self.rng.borrow_mut().fill_bytes(bytes)
173 }
174
175 #[inline]
176 fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> std::result::Result<(), rand_core::Error> {
177 (self.rng.borrow_mut()).try_fill_bytes(bytes)
178 }
179}
180
181#[inline]
184pub fn random<T>() -> T
185where
186 Standard: Distribution<T>,
187{
188 thread_rng().r#gen()
189}
190
191#[inline]
193pub fn random_uuid() -> Uuid {
194 let mut bytes = [0; 16];
195 thread_rng().fill_bytes(&mut bytes);
196 Builder::from_random_bytes(bytes).into_uuid()
197}