enum_derived/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::{
4    collections::{HashMap, HashSet},
5    hash::Hash,
6    mem::{self, MaybeUninit},
7    num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping},
8};
9
10#[doc(hidden)]
11pub use rand as __rand;
12
13/// Derive [Rand] for any enum or struct
14pub use enum_derived_macro::Rand;
15
16/// Generate a random version of the implementor
17pub trait Rand {
18    fn rand() -> Self;
19}
20
21impl<K: Rand + Hash + Eq, V: Rand> Rand for HashMap<K, V> {
22    fn rand() -> Self {
23        let mut map = HashMap::new();
24        let size = (rand::random::<usize>() % 15) + 1;
25        for _ in 0..size {
26            let k = K::rand();
27            let v = V::rand();
28            let _ = map.insert(k, v);
29        }
30        map
31    }
32}
33
34impl<K: Rand + Hash + Eq> Rand for HashSet<K> {
35    fn rand() -> Self {
36        let mut set = HashSet::new();
37        let size = (rand::random::<usize>() % 15) + 1;
38        for _ in 0..size {
39            let k = K::rand();
40            let _ = set.insert(k);
41        }
42        set
43    }
44}
45
46impl<T: Rand> Rand for Option<T> {
47    fn rand() -> Self {
48        if bool::rand() {
49            Some(T::rand())
50        } else {
51            None
52        }
53    }
54}
55
56impl<T: Rand> Rand for Wrapping<T> {
57    fn rand() -> Self {
58        Wrapping(T::rand())
59    }
60}
61
62impl<T: Rand> Rand for Vec<T> {
63    fn rand() -> Self {
64        let size = (rand::random::<usize>() % 63) + 1;
65        let mut out = Vec::with_capacity(size);
66
67        for _ in 0..size {
68            out.push(T::rand());
69        }
70
71        debug_assert!(out.len() == size);
72        out
73    }
74}
75
76impl Rand for String {
77    fn rand() -> Self {
78        let size = (rand::random::<usize>() % 63) + 1;
79        let mut out = Vec::with_capacity(size);
80
81        for _ in 0..size {
82            out.push(char::rand());
83        }
84
85        debug_assert!(out.len() == size);
86        String::from_iter(out.iter())
87    }
88}
89
90impl<T: Rand, const N: usize> Rand for [T; N] {
91    fn rand() -> Self {
92        let mut buff: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
93
94        for elem in &mut buff {
95            *elem = MaybeUninit::new(T::rand());
96        }
97
98        unsafe { mem::transmute_copy::<_, _>(&buff) }
99    }
100}
101
102macro_rules! impl_rand {
103    ($type:ty) => {
104        impl Rand for $type {
105            fn rand() -> Self {
106                ::rand::random()
107            }
108        }
109    };
110}
111
112impl_rand!(bool);
113impl_rand!(char);
114impl_rand!(f32);
115impl_rand!(f64);
116impl_rand!(i8);
117impl_rand!(i16);
118impl_rand!(i32);
119impl_rand!(i64);
120impl_rand!(i128);
121impl_rand!(isize);
122impl_rand!(u8);
123impl_rand!(u16);
124impl_rand!(u32);
125impl_rand!(u64);
126impl_rand!(u128);
127impl_rand!(());
128impl_rand!(usize);
129impl_rand!(NonZeroU8);
130impl_rand!(NonZeroU16);
131impl_rand!(NonZeroU32);
132impl_rand!(NonZeroU64);
133impl_rand!(NonZeroU128);
134impl_rand!(NonZeroUsize);
135
136macro_rules! impl_tuple_rand {
137    // use variables to indicate the arity of the tuple
138    ($($tyvar:ident),* ) => {
139        // the trailing commas are for the 1 tuple
140        impl< $( $tyvar ),* >
141            Rand
142            for ( $( $tyvar ),* , )
143            where $( $tyvar: Rand ),*
144        {
145            #[inline]
146            fn rand() -> ( $( $tyvar ),* , ) {
147                (
148                    // use the $tyvar's to get the appropriate number of
149                    // repeats (they're not actually needed)
150                    $(
151                        <$tyvar as Rand>::rand()
152                    ),*
153                    ,
154                )
155            }
156        }
157    }
158}
159
160impl_tuple_rand! {A}
161impl_tuple_rand! {A, B}
162impl_tuple_rand! {A, B, C}
163impl_tuple_rand! {A, B, C, D}
164impl_tuple_rand! {A, B, C, D, E}
165impl_tuple_rand! {A, B, C, D, E, F}
166impl_tuple_rand! {A, B, C, D, E, F, G}
167impl_tuple_rand! {A, B, C, D, E, F, G, H}
168impl_tuple_rand! {A, B, C, D, E, F, G, H, I}
169impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J}
170impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K}
171impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L}
172impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L, M}
173impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L, M, N}
174impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O}
175impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P}
176impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q}
177impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R}
178impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S}
179impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T}
180impl_tuple_rand! {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U}