1#[cfg(feature = "derive")]
34pub use generate_random_macro::GenerateRandom;
35
36pub use rand::Rng;
37
38pub fn generate<T, R>(rng: &mut R) -> T
40where
41 T: GenerateRandom,
42 R: Rng,
43{
44 GenerateRandom::generate_random(rng)
45}
46
47pub trait GenerateRandom {
52 fn generate_random<R: Rng + ?Sized>(rng: &mut R) -> Self;
54}
55
56macro_rules! impl_generate_random {
57 ( $( $t:ty, )+ ) => {
58 $(
59 impl GenerateRandom for $t {
60 fn generate_random<R: Rng + ?Sized>(rng: &mut R) -> Self {
61 rng.gen()
62 }
63 }
64 )+
65 }
66}
67
68impl_generate_random! {
69 bool,
70 char,
71 u8,
72 i8,
73 u16,
74 i16,
75 u32,
76 i32,
77 u64,
78 i64,
79 u128,
80 i128,
81 usize,
82 isize,
83 f32,
84 f64,
85}
86
87impl<T: GenerateRandom> GenerateRandom for Option<T> {
88 fn generate_random<R: Rng + ?Sized>(rng: &mut R) -> Self {
89 if bool::generate_random(rng) {
90 Some(T::generate_random(rng))
91 } else {
92 None
93 }
94 }
95}
96
97macro_rules! impl_generate_random_tuple {
98 ( $t0:ident $( $t:ident )* ) => {
99 impl< $t0, $( $t, )* > GenerateRandom for ( $t0, $( $t, )* )
100 where
101 $t0: GenerateRandom,
102 $(
103 $t: GenerateRandom,
104 )*
105 {
106 fn generate_random<R: Rng + ?Sized>(rng: &mut R) -> Self {
107 (
108 $t0::generate_random(rng),
109 $(
110 $t::generate_random(rng),
111 )*
112 )
113 }
114 }
115 impl_generate_random_tuple!( $( $t )* );
116 };
117 () => {
118 impl GenerateRandom for () {
119 fn generate_random<R: Rng + ?Sized>(_rng: &mut R) -> Self {
120 ()
121 }
122 }
123 }
124}
125
126impl_generate_random_tuple!(A B C D E F G H I J K L);
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 fn rng() -> impl rand::Rng {
133 use rand::SeedableRng;
134 rand_chacha::ChaCha8Rng::from(rand_chacha::ChaCha8Core::from_seed([37; 32]))
135 }
136
137 #[test]
138 fn test_u8() {
139 let mut rng = rng();
140 assert_eq!(u8::generate_random(&mut rng), 55);
141 }
142}