1use core::char;
12use core::num::Wrapping;
13#[cfg(feature = "alloc")]
14use alloc::string::String;
15
16use crate::distributions::{Distribution, Standard, Uniform};
17#[cfg(feature = "alloc")]
18use crate::distributions::DistString;
19use crate::Rng;
20
21#[cfg(feature = "serde1")]
22use serde::{Serialize, Deserialize};
23#[cfg(feature = "min_const_gen")]
24use std::mem::{self, MaybeUninit};
25
26
27#[derive(Debug, Clone, Copy)]
65#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
66pub struct Alphanumeric;
67
68
69impl Distribution<char> for Standard {
72 #[inline]
73 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
74 const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1;
79
80 let range = Uniform::new(GAP_SIZE, 0x11_0000);
83
84 let mut n = range.sample(rng);
85 if n <= 0xDFFF {
86 n -= GAP_SIZE;
87 }
88 unsafe { char::from_u32_unchecked(n) }
89 }
90}
91
92#[cfg(feature = "alloc")]
95impl DistString for Standard {
96 fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, s: &mut String, len: usize) {
97 s.reserve(4 * len);
101 s.extend(Distribution::<char>::sample_iter(self, rng).take(len));
102 }
103}
104
105impl Distribution<u8> for Alphanumeric {
106 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
107 const RANGE: u32 = 26 + 26 + 10;
108 const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
109 abcdefghijklmnopqrstuvwxyz\
110 0123456789";
111 loop {
116 let var = rng.next_u32() >> (32 - 6);
117 if var < RANGE {
118 return GEN_ASCII_STR_CHARSET[var as usize];
119 }
120 }
121 }
122}
123
124#[cfg(feature = "alloc")]
125impl DistString for Alphanumeric {
126 fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize) {
127 unsafe {
128 let v = string.as_mut_vec();
129 v.extend(self.sample_iter(rng).take(len));
130 }
131 }
132}
133
134impl Distribution<bool> for Standard {
135 #[inline]
136 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
137 (rng.next_u32() as i32) < 0
142 }
143}
144
145macro_rules! tuple_impl {
146 ($($tyvar:ident),* ) => {
148 impl< $( $tyvar ),* >
150 Distribution<( $( $tyvar ),* , )>
151 for Standard
152 where $( Standard: Distribution<$tyvar> ),*
153 {
154 #[inline]
155 fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> ( $( $tyvar ),* , ) {
156 (
157 $(
160 _rng.gen::<$tyvar>()
161 ),*
162 ,
163 )
164 }
165 }
166 }
167}
168
169impl Distribution<()> for Standard {
170 #[allow(clippy::unused_unit)]
171 #[inline]
172 fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> () {
173 ()
174 }
175}
176tuple_impl! {A}
177tuple_impl! {A, B}
178tuple_impl! {A, B, C}
179tuple_impl! {A, B, C, D}
180tuple_impl! {A, B, C, D, E}
181tuple_impl! {A, B, C, D, E, F}
182tuple_impl! {A, B, C, D, E, F, G}
183tuple_impl! {A, B, C, D, E, F, G, H}
184tuple_impl! {A, B, C, D, E, F, G, H, I}
185tuple_impl! {A, B, C, D, E, F, G, H, I, J}
186tuple_impl! {A, B, C, D, E, F, G, H, I, J, K}
187tuple_impl! {A, B, C, D, E, F, G, H, I, J, K, L}
188
189#[cfg(feature = "min_const_gen")]
190impl<T, const N: usize> Distribution<[T; N]> for Standard
191where Standard: Distribution<T>
192{
193 #[inline]
194 fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; N] {
195 let mut buff: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
196
197 for elem in &mut buff {
198 *elem = MaybeUninit::new(_rng.gen());
199 }
200
201 unsafe { mem::transmute_copy::<_, _>(&buff) }
202 }
203}
204
205#[cfg(not(feature = "min_const_gen"))]
206macro_rules! array_impl {
207 {$n:expr, $t:ident, $($ts:ident,)*} => {
209 array_impl!{($n - 1), $($ts,)*}
210
211 impl<T> Distribution<[T; $n]> for Standard where Standard: Distribution<T> {
212 #[inline]
213 fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] {
214 [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
215 }
216 }
217 };
218 {$n:expr,} => {
220 impl<T> Distribution<[T; $n]> for Standard {
221 fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] { [] }
222 }
223 };
224}
225
226#[cfg(not(feature = "min_const_gen"))]
227array_impl! {32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}
228
229impl<T> Distribution<Option<T>> for Standard
230where Standard: Distribution<T>
231{
232 #[inline]
233 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T> {
234 if rng.gen::<bool>() {
236 Some(rng.gen())
237 } else {
238 None
239 }
240 }
241}
242
243impl<T> Distribution<Wrapping<T>> for Standard
244where Standard: Distribution<T>
245{
246 #[inline]
247 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Wrapping<T> {
248 Wrapping(rng.gen())
249 }
250}
251
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256 use crate::RngCore;
257 #[cfg(feature = "alloc")] use alloc::string::String;
258
259 #[test]
260 fn test_misc() {
261 let rng: &mut dyn RngCore = &mut crate::test::rng(820);
262
263 rng.sample::<char, _>(Standard);
264 rng.sample::<bool, _>(Standard);
265 }
266
267 #[cfg(feature = "alloc")]
268 #[test]
269 fn test_chars() {
270 use core::iter;
271 let mut rng = crate::test::rng(805);
272
273 let word: String = iter::repeat(())
276 .map(|()| rng.gen::<char>())
277 .take(1000)
278 .collect();
279 assert!(!word.is_empty());
280 }
281
282 #[test]
283 fn test_alphanumeric() {
284 let mut rng = crate::test::rng(806);
285
286 let mut incorrect = false;
289 for _ in 0..100 {
290 let c: char = rng.sample(Alphanumeric).into();
291 incorrect |= !(('0'..='9').contains(&c) ||
292 ('A'..='Z').contains(&c) ||
293 ('a'..='z').contains(&c) );
294 }
295 assert!(!incorrect);
296 }
297
298 #[test]
299 fn value_stability() {
300 fn test_samples<T: Copy + core::fmt::Debug + PartialEq, D: Distribution<T>>(
301 distr: &D, zero: T, expected: &[T],
302 ) {
303 let mut rng = crate::test::rng(807);
304 let mut buf = [zero; 5];
305 for x in &mut buf {
306 *x = rng.sample(&distr);
307 }
308 assert_eq!(&buf, expected);
309 }
310
311 test_samples(&Standard, 'a', &[
312 '\u{8cdac}',
313 '\u{a346a}',
314 '\u{80120}',
315 '\u{ed692}',
316 '\u{35888}',
317 ]);
318 test_samples(&Alphanumeric, 0, &[104, 109, 101, 51, 77]);
319 test_samples(&Standard, false, &[true, true, false, true, false]);
320 test_samples(&Standard, None as Option<bool>, &[
321 Some(true),
322 None,
323 Some(false),
324 None,
325 Some(false),
326 ]);
327 test_samples(&Standard, Wrapping(0i32), &[
328 Wrapping(-2074640887),
329 Wrapping(-1719949321),
330 Wrapping(2018088303),
331 Wrapping(-547181756),
332 Wrapping(838957336),
333 ]);
334
335 test_samples(&Standard, (), &[(), (), (), (), ()]);
337 test_samples(&Standard, (false,), &[
338 (true,),
339 (true,),
340 (false,),
341 (true,),
342 (false,),
343 ]);
344 test_samples(&Standard, (false, false), &[
345 (true, true),
346 (false, true),
347 (false, false),
348 (true, false),
349 (false, false),
350 ]);
351
352 test_samples(&Standard, [0u8; 0], &[[], [], [], [], []]);
353 test_samples(&Standard, [0u8; 3], &[
354 [9, 247, 111],
355 [68, 24, 13],
356 [174, 19, 194],
357 [172, 69, 213],
358 [149, 207, 29],
359 ]);
360 }
361}