1use rand::{Error, RngCore};
2use crate::internal;
3
4pub fn get_random() -> u64 {
17 internal::dispatch_random()
18}
19
20pub fn random_choice<T>(slice: &[T]) -> Option<&T> {
39 match slice {
40 [] => None,
41 [x] => Some(x),
42 _ => {
43 let idx: usize = (get_random() as usize) % slice.len();
44 Some(&slice[idx])
45 }
46 }
47}
48
49pub struct AntithesisRng;
69
70impl RngCore for AntithesisRng {
71 fn next_u32(&mut self) -> u32 {
72 get_random() as u32
73 }
74
75 fn next_u64(&mut self) -> u64 {
76 get_random()
77 }
78
79 fn fill_bytes(&mut self, dest: &mut [u8]) {
80 let mut chunks = dest.chunks_exact_mut(8);
83
84 for chunk in chunks.by_ref() {
86 let random_bytes = self.next_u64().to_ne_bytes();
88 chunk.copy_from_slice(&random_bytes);
90 }
91
92 let remainder = chunks.into_remainder();
94
95 if !remainder.is_empty() {
96 let random_bytes = self.next_u64().to_ne_bytes();
98 remainder.copy_from_slice(&random_bytes[..remainder.len()]);
100 }
101 }
102
103 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
104 self.fill_bytes(dest);
105 Ok(())
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112 use std::collections::{HashMap, HashSet};
113 use rand::Rng;
114 use rand::seq::SliceRandom;
115
116 #[test]
117 fn random_choice_no_choices() {
118 let array = [""; 0];
119 assert_eq!(0, array.len());
120 assert_eq!(None, random_choice(&array))
121 }
122
123 #[test]
124 fn random_choice_one_choice() {
125 let array = ["ABc"; 1];
126 assert_eq!(1, array.len());
127 assert_eq!(Some(&"ABc"), random_choice(&array))
128 }
129
130 #[test]
131 fn random_choice_few_choices() {
132 let mut counted_items: HashMap<&str, i64> = HashMap::new();
135 counted_items.insert("a", 0);
136 counted_items.insert("b", 0);
137 counted_items.insert("c", 0);
138
139 let all_keys: Vec<&str> = counted_items.keys().cloned().collect();
140 assert_eq!(counted_items.len(), all_keys.len());
141 for _i in 0..15 {
142 let rc = random_choice(all_keys.as_slice());
143 if let Some(choice) = rc {
144 if let Some(x) = counted_items.get_mut(choice) {
145 *x += 1;
146 }
147 }
148 }
149 for (key, val) in counted_items.iter() {
150 assert_ne!(*val, 0, "Did not produce the choice: {}", key);
151 }
152 }
153
154 #[test]
155 fn get_random_100k() {
156 let mut random_numbers: HashSet<u64> = HashSet::new();
157 for _i in 0..100000 {
158 let rn = get_random();
159 assert!(!random_numbers.contains(&rn));
160 random_numbers.insert(rn);
161 }
162 }
163
164 #[test]
165 fn rng_no_choices() {
166 let mut rng = AntithesisRng;
167 let array = [""; 0];
168 assert_eq!(0, array.len());
169 assert_eq!(None, array.choose(&mut rng));
170 }
171
172 #[test]
173 fn rng_one_choice() {
174 let mut rng = AntithesisRng;
175 let array = ["ABc"; 1];
176 assert_eq!(1, array.len());
177 assert_eq!(Some(&"ABc"), array.choose(&mut rng));
178 }
179
180 #[test]
181 fn rng_few_choices() {
182 let mut rng = AntithesisRng;
183 let mut counted_items: HashMap<&str, i64> = HashMap::new();
186 counted_items.insert("a", 0);
187 counted_items.insert("b", 0);
188 counted_items.insert("c", 0);
189
190 let all_keys: Vec<&str> = counted_items.keys().cloned().collect();
191 assert_eq!(counted_items.len(), all_keys.len());
192 for _i in 0..15 {
193 let rc = all_keys.choose(&mut rng);
194 if let Some(choice) = rc {
195 if let Some(x) = counted_items.get_mut(choice) {
196 *x += 1;
197 }
198 }
199 }
200 for (key, val) in counted_items.iter() {
201 assert_ne!(*val, 0, "Did not produce the choice: {}", key);
202 }
203 }
204
205 #[test]
206 fn rng_100k() {
207 let mut rng = AntithesisRng;
208 let mut random_numbers: HashSet<u64> = HashSet::new();
209 for _i in 0..100000 {
210 let rn: u64 = rng.gen();
211 assert!(!random_numbers.contains(&rn));
212 random_numbers.insert(rn);
213 }
214 }
215}