1 //! Generate random data.
6 //! use generate_random::GenerateRandom;
8 //! #[derive(GenerateRandom)]
15 //! // Providing a weight allows changing the probabilities.
16 //! // This variant is now twice as likely to be generated as the others.
21 //! let mut rng = rand::thread_rng();
22 //! let my_value = MyEnum::generate_random(&mut rng);
25 /// This derive macro provides an implementation
26 /// of the [`trait@GenerateRandom`] trait.
28 /// Enum variants can be given a `weight` attribute
29 /// to change how often it is generated.
30 /// By default, the weight is `1`.
31 /// The probability of a variants is its weight
32 /// divided by the sum over all variants.
33 pub use generate_random_macro::GenerateRandom;
35 /// Enable randomly generating values of a type.
37 /// This trait can be implemented using the derive
38 /// macro of the same name: [`macro@GenerateRandom`].
39 pub trait GenerateRandom {
40 /// Create a new random value of this type.
41 fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self;
44 macro_rules! impl_generate_random {
47 impl GenerateRandom for $t {
48 fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
56 impl_generate_random! {
75 impl<T: GenerateRandom> GenerateRandom for Option<T> {
76 fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
77 if bool::generate_random(rng) {
78 Some(T::generate_random(rng))
85 impl<T: GenerateRandom, const N: usize> GenerateRandom for [T; N] {
86 fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
87 use core::mem::MaybeUninit;
89 let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
91 for elem in arr.iter_mut() {
92 *elem = MaybeUninit::new(T::generate_random(rng));
95 let ret = unsafe { std::mem::transmute_copy(&arr) };
96 std::mem::forget(arr);
102 impl GenerateRandom for String {
103 fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
104 use rand::distributions::{Alphanumeric, DistString};
106 let len = rng.gen_range(0..32);
107 Alphanumeric.sample_string(rng, len)
111 impl<T: GenerateRandom> GenerateRandom for Vec<T> {
112 fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
113 let len = rng.gen_range(0..8);
114 (0..len).map(|_| T::generate_random(rng)).collect()
118 impl<K, V> GenerateRandom for std::collections::HashMap<K, V>
120 K: GenerateRandom + std::cmp::Eq + std::hash::Hash,
123 fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
124 let len = rng.gen_range(0..8);
126 .map(|_| (K::generate_random(rng), V::generate_random(rng)))
131 macro_rules! impl_generate_random_tuple {
132 ( $t0:ident $( $t:ident )* ) => {
133 impl< $t0, $( $t, )* > GenerateRandom for ( $t0, $( $t, )* )
140 fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
142 $t0::generate_random(rng),
144 $t::generate_random(rng),
149 impl_generate_random_tuple!( $( $t )* );
152 impl GenerateRandom for () {
153 fn generate_random<R: rand::Rng + ?Sized>(_rng: &mut R) -> Self {
160 impl_generate_random_tuple!(A B C D E F G H I J K L);
166 fn rng() -> impl rand::Rng {
167 use rand::SeedableRng;
168 rand_chacha::ChaCha8Rng::from(rand_chacha::ChaCha8Core::from_seed([37; 32]))
174 assert_eq!(u8::generate_random(&mut rng), 55);