1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
macro_rules! gen_int_const {
    ($func:ident, $int:ty, $doc:tt) => {
        #[doc = $doc]
        #[inline]
        fn $func(&self) -> $int {
            <$int>::from_le_bytes(self.gen())
        }
    };
}

macro_rules! trait_range_int {
    ($value:tt, $unsigned:tt, $bigger:ty, $source:ident, $doc:tt) => {
        #[doc = $doc]
        ///
        /// # Panics
        ///
        /// Panics if the range is empty or invalid.
        #[inline]
        fn $value(&self, bounds: impl RangeBounds<$value>) -> $value {
            const BITS: $bigger = $value::BITS as $bigger;

            let lower = match bounds.start_bound() {
                Bound::Included(lower) => *lower,
                Bound::Excluded(lower) => lower.saturating_add(1),
                Bound::Unbounded => $value::MIN,
            };
            let upper = match bounds.end_bound() {
                Bound::Included(upper) => *upper,
                Bound::Excluded(upper) => upper.saturating_sub(1),
                Bound::Unbounded => $value::MAX,
            };

            assert!(lower <= upper, "Range should not be zero sized or invalid");

            match (lower, upper) {
                ($value::MIN, $value::MAX) => self.$source(),
                (_, _) => {
                    let range = upper.wrapping_sub(lower).wrapping_add(1) as $unsigned;
                    let mut generated = self.$source() as $unsigned;
                    let mut high = (generated as $bigger).wrapping_mul(range as $bigger);
                    let mut low = high as $unsigned;
                    if low < range {
                        let threshold = range.wrapping_neg() % range;
                        while low < threshold {
                            generated = self.$source() as $unsigned;
                            high = (generated as $bigger).wrapping_mul(range as $bigger);
                            low = high as $unsigned;
                        }
                    }
                    let value = (high >> BITS) as $value;
                    lower.wrapping_add(value)
                }
            }
        }
    };
}

macro_rules! trait_float_gen {
    ($name:ident, $value:tt, $int:ty, $scale:expr, $source:ident, $doc:tt) => {
        #[doc = $doc]
        #[inline]
        fn $name(&self) -> $value {
            const FLOAT_SIZE: u32 = (core::mem::size_of::<$value>() as u32) * 8;
            const SCALE: $value = $scale / ((1 as $int << <$value>::MANTISSA_DIGITS) as $value);

            let value = self.$source() >> (FLOAT_SIZE - <$value>::MANTISSA_DIGITS);

            SCALE * (value as $value)
        }
    };
}

macro_rules! trait_rand_chars {
    ($func:ident, $chars:expr, $doc:tt) => {
        #[doc = $doc]
        #[inline]
        fn $func(&self) -> char {
            const CHARS: &[u8] = $chars;

            self.sample(CHARS).map(|&value| value as char).unwrap()
        }
    };
}