fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self;
}
+/// Enable randomly generating values of an enum
+/// with a predefined variant
+///
+/// This trait is automatically implemented for enums
+/// by the [`macro@GenerateRandom`] macro
+pub trait GenerateRandomVariant {
+ /// Return number of variants
+ fn num_variants() -> usize;
+
+ /// Return name of variant with index
+ fn variant_name(variant: usize) -> &'static str;
+
+ /// Create a randomly generated value with a predefied variant
+ fn generate_random_variant<R: rand::Rng + ?Sized>(rng: &mut R, variant: usize) -> Self;
+}
+
macro_rules! impl_generate_random {
( $( $t:ty, )+ ) => {
$(
impl<T: GenerateRandom, const N: usize> GenerateRandom for [T; N] {
fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
- use core::mem::MaybeUninit;
-
- let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
-
- for elem in arr.iter_mut() {
- *elem = MaybeUninit::new(T::generate_random(rng));
- }
-
- let ret = unsafe { std::mem::transmute_copy(&arr) };
- std::mem::forget(arr);
-
- ret
+ core::array::from_fn(|_| T::generate_random(rng))
}
}
}
}
+impl<T: GenerateRandom> GenerateRandom for Vec<T> {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ let len = rng.gen_range(0..8);
+ (0..len).map(|_| T::generate_random(rng)).collect()
+ }
+}
+
+impl<T> GenerateRandom for std::collections::HashSet<T>
+where
+ T: GenerateRandom + std::cmp::Eq + std::hash::Hash,
+{
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ let len = rng.gen_range(0..8);
+ (0..len).map(|_| T::generate_random(rng)).collect()
+ }
+}
+
+impl<K, V> GenerateRandom for std::collections::HashMap<K, V>
+where
+ K: GenerateRandom + std::cmp::Eq + std::hash::Hash,
+ V: GenerateRandom,
+{
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ let len = rng.gen_range(0..8);
+ (0..len)
+ .map(|_| (K::generate_random(rng), V::generate_random(rng)))
+ .collect()
+ }
+}
+
+impl<T: GenerateRandom> GenerateRandom for Box<T> {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ Box::new(T::generate_random(rng))
+ }
+}
+
+impl<T: GenerateRandom> GenerateRandom for std::ops::Range<T> {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ T::generate_random(rng)..T::generate_random(rng)
+ }
+}
+
+impl<T: GenerateRandom> GenerateRandom for std::ops::RangeFrom<T> {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ T::generate_random(rng)..
+ }
+}
+
+impl GenerateRandom for std::ops::RangeFull {
+ fn generate_random<R: rand::Rng + ?Sized>(_rng: &mut R) -> Self {
+ ..
+ }
+}
+
+impl<T: GenerateRandom> GenerateRandom for std::ops::RangeInclusive<T> {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ T::generate_random(rng)..=T::generate_random(rng)
+ }
+}
+
+impl<T: GenerateRandom> GenerateRandom for std::ops::RangeTo<T> {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ ..T::generate_random(rng)
+ }
+}
+impl<T: GenerateRandom> GenerateRandom for std::ops::RangeToInclusive<T> {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ ..=T::generate_random(rng)
+ }
+}
+
+#[cfg(feature = "enumset")]
+impl<T: enumset::EnumSetType + GenerateRandom> GenerateRandom for enumset::EnumSet<T> {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ let max = enumset::EnumSet::<T>::variant_count() * 2;
+ let len = rng.gen_range(0..max);
+
+ (0..len).map(|_| T::generate_random(rng)).collect()
+ }
+}
+
macro_rules! impl_generate_random_tuple {
( $t0:ident $( $t:ident )* ) => {
impl< $t0, $( $t, )* > GenerateRandom for ( $t0, $( $t, )* )