1pub use autorand_derive::Random;
2pub use rand;
3
4use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, LinkedList, VecDeque};
5use std::hash::{BuildHasher, Hash};
6
7use rand::{distributions::Alphanumeric, Rng};
8
9const LEN_LIMIT: usize = 16;
10
11const UINT_LIMIT: usize = u16::max_value() as usize;
12const INT_LOWER_LIMIT: isize = 0 - (UINT_LIMIT as isize);
13const INT_UPPER_LIMIT: isize = UINT_LIMIT as isize;
14
15pub trait Random: Sized {
16 fn random() -> Self;
17}
18
19impl<T: Random> Random for Option<T> {
20 fn random() -> Self {
21 if rand::random::<bool>() {
22 Some(T::random())
23 } else {
24 None
25 }
26 }
27}
28
29impl Random for String {
30 fn random() -> Self {
31 let mut rng = rand::thread_rng();
32 let length = rng.gen_range(0, LEN_LIMIT);
33 rng.sample_iter(&Alphanumeric).take(length).collect()
34 }
35}
36
37impl<T: Random> Random for Vec<T> {
38 fn random() -> Self {
39 rand_length_iter().collect()
40 }
41}
42
43impl<K: Random + Eq + Hash, V: Random, S: BuildHasher + Default> Random for HashMap<K, V, S> {
44 fn random() -> Self {
45 rand_length_iter::<(K, V)>().collect()
46 }
47}
48
49impl<K: Random + Ord, V: Random> Random for BTreeMap<K, V> {
50 fn random() -> Self {
51 rand_length_iter::<(K, V)>().collect()
52 }
53}
54
55impl<T: Random + Eq + Hash, S: BuildHasher + Default> Random for HashSet<T, S> {
56 fn random() -> Self {
57 rand_length_iter().collect()
58 }
59}
60
61impl<T: Random + Ord> Random for BTreeSet<T> {
62 fn random() -> Self {
63 rand_length_iter().collect()
64 }
65}
66
67impl<T: Random> Random for VecDeque<T> {
68 fn random() -> Self {
69 rand_length_iter().collect()
70 }
71}
72
73impl<T: Random> Random for LinkedList<T> {
74 fn random() -> Self {
75 rand_length_iter().collect()
76 }
77}
78
79fn rand_length_iter<T: Random>() -> impl Iterator<Item = T> {
80 let length = rand::thread_rng().gen_range(0, LEN_LIMIT);
81 rand_iter().take(length)
82}
83
84fn rand_iter<T: Random>() -> impl Iterator<Item = T> {
85 (0..).map(|_| T::random())
86}
87
88impl Random for f32 {
89 fn random() -> Self {
90 let base = rand::random::<f32>();
91 (base * 1000.0).ceil() / 1000.0
92 }
93}
94
95impl Random for f64 {
96 fn random() -> Self {
97 let base = rand::random::<f64>();
98 (base * 1000.0).ceil() / 1000.0
99 }
100}
101
102macro_rules! impl_primitives_unsigned {
103 ($($t:tt,)*) => {
104 $(
105 impl Random for $t {
106 fn random() -> Self {
107 let mut rng = rand::thread_rng();
108 if cfg!(not(feature = "limited-integers")) || ($t::max_value() as usize) < UINT_LIMIT {
109 rng.gen_range(0, $t::max_value())
110 } else {
111 rng.gen_range(0, UINT_LIMIT as $t)
112 }
113 }
114 }
115 )*
116 };
117}
118
119macro_rules! impl_primitives_signed {
120 ($($t:tt,)*) => {
121 $(
122 impl Random for $t {
123 fn random() -> Self {
124 let mut rng = rand::thread_rng();
125 if cfg!(not(feature = "limited-integers")) || ($t::max_value() as isize) < INT_UPPER_LIMIT {
126 rng.gen_range($t::min_value(), $t::max_value())
127 } else {
128 rng.gen_range(INT_LOWER_LIMIT as $t, INT_UPPER_LIMIT as $t)
129 }
130 }
131 }
132 )*
133 };
134}
135
136#[rustfmt::skip]
137impl_primitives_signed! {
138 i8, i16, i32, i64, isize,
139}
140
141impl_primitives_unsigned! {
142 u8, u16, u32, u64, usize,
143}
144
145impl Random for char {
146 fn random() -> Self {
147 rand::random()
148 }
149}
150
151impl Random for bool {
152 fn random() -> Self {
153 rand::random()
154 }
155}
156
157macro_rules! impl_arrays {
158 ($($s:expr,)*) => {
159 $(
160 impl<T: Random> Random for [T; $s] {
161 fn random() -> Self {
162 use std::mem::{MaybeUninit, transmute_copy, size_of};
163 unsafe {
164 let mut array: [MaybeUninit<T>; $s] = MaybeUninit::uninit().assume_init();
165 for elem in &mut array[..] {
166 *elem = MaybeUninit::new(T::random());
167 }
168
169 debug_assert!(size_of::<[MaybeUninit<T>; $s]>() == size_of::<[T; $s]>());
171 transmute_copy::<_, [T; $s]>(&array)
172 }
173 }
174 }
175 )*
176 };
177}
178
179#[rustfmt::skip]
180impl_arrays!(
181 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
182 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32,
183 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
184);
185
186macro_rules! impl_tuples {
187 ($([$($t:tt)*],)*) => {
188 $(
189 impl<$($t:Random,)*> Random for ($($t,)*) {
190 fn random() -> Self {
191 ($($t::random(),)*)
192 }
193 }
194 )*
195 };
196}
197
198impl_tuples!(
199 [A],
200 [A B],
201 [A B C],
202 [A B C D],
203 [A B C D E],
204 [A B C D E F],
205 [A B C D E F G],
206 [A B C D E F G H],
207 [A B C D E F G H I],
208 [A B C D E F G H I J],
209 [A B C D E F G H I J K],
210);
211
212#[cfg(feature = "json")]
213impl Random for serde_json::Map<String, serde_json::Value> {
214 fn random() -> Self {
215 rand_length_iter().collect()
216 }
217}
218
219#[cfg(feature = "json")]
220impl Random for serde_json::Number {
221 fn random() -> Self {
222 serde_json::Number::from_f64(Random::random()).unwrap()
223 }
224}
225
226#[cfg(feature = "json")]
227#[cfg(not(feature = "json-value-always-null"))]
228impl Random for serde_json::Value {
229 fn random() -> Self {
230 use serde_json::Value;
231 let variant = rand::thread_rng().gen_range(0u8, 6);
232 match variant {
233 0 => Value::Number(Random::random()),
234 1 => Value::Bool(Random::random()),
235 2 => Value::String(Random::random()),
236 3 => Value::Array(Random::random()),
237 4 => Value::Null,
238 5 => Value::Object(Random::random()),
239 _ => unreachable!(),
240 }
241 }
242}
243
244#[cfg(feature = "json")]
245#[cfg(feature = "json-value-always-null")]
246impl Random for serde_json::Value {
247 fn random() -> Self {
248 use serde_json::Value;
249 Value::Null
250 }
251}