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