use super::{
BoolGenerator, BoxedGenerator, CharactersGenerator, DurationGenerator, FloatGenerator,
Generator, HashMapGenerator, IntegerGenerator, OptionalGenerator, TextGenerator, VecGenerator,
booleans, characters, collections::ArrayGenerator, durations, floats, hashmaps, integers,
optional, text, vecs,
};
use std::collections::HashMap;
use std::hash::Hash;
use std::time::Duration;
pub trait DefaultGenerator: Sized {
type Generator: super::Generator<Self> + 'static;
fn default_generator() -> Self::Generator;
}
pub fn default<T: DefaultGenerator>() -> BoxedGenerator<'static, T> {
T::default_generator().boxed()
}
impl DefaultGenerator for bool {
type Generator = BoolGenerator;
fn default_generator() -> Self::Generator {
booleans()
}
}
impl DefaultGenerator for String {
type Generator = TextGenerator;
fn default_generator() -> Self::Generator {
text()
}
}
impl DefaultGenerator for char {
type Generator = CharactersGenerator;
fn default_generator() -> Self::Generator {
characters()
}
}
impl DefaultGenerator for i8 {
type Generator = IntegerGenerator<i8>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for i16 {
type Generator = IntegerGenerator<i16>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for i32 {
type Generator = IntegerGenerator<i32>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for i64 {
type Generator = IntegerGenerator<i64>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for u8 {
type Generator = IntegerGenerator<u8>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for u16 {
type Generator = IntegerGenerator<u16>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for u32 {
type Generator = IntegerGenerator<u32>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for u64 {
type Generator = IntegerGenerator<u64>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for i128 {
type Generator = IntegerGenerator<i128>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for u128 {
type Generator = IntegerGenerator<u128>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for isize {
type Generator = IntegerGenerator<isize>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for usize {
type Generator = IntegerGenerator<usize>;
fn default_generator() -> Self::Generator {
integers()
}
}
impl DefaultGenerator for f32 {
type Generator = FloatGenerator<f32>;
fn default_generator() -> Self::Generator {
floats()
}
}
impl DefaultGenerator for f64 {
type Generator = FloatGenerator<f64>;
fn default_generator() -> Self::Generator {
floats()
}
}
impl<T: DefaultGenerator + 'static> DefaultGenerator for Option<T>
where
T::Generator: Send + Sync,
{
type Generator = OptionalGenerator<T::Generator, T>;
fn default_generator() -> Self::Generator {
optional(T::default_generator())
}
}
impl<T: DefaultGenerator + 'static> DefaultGenerator for Vec<T>
where
T::Generator: Send + Sync,
{
type Generator = VecGenerator<T::Generator, T>;
fn default_generator() -> Self::Generator {
vecs(T::default_generator())
}
}
impl<T: DefaultGenerator + 'static, const N: usize> DefaultGenerator for [T; N]
where
T::Generator: Send + Sync,
{
type Generator = ArrayGenerator<T::Generator, T, N>;
fn default_generator() -> Self::Generator {
ArrayGenerator::new(T::default_generator())
}
}
impl DefaultGenerator for Duration {
type Generator = DurationGenerator;
fn default_generator() -> Self::Generator {
durations()
}
}
impl<K: DefaultGenerator + 'static, V: DefaultGenerator + 'static> DefaultGenerator
for HashMap<K, V>
where
K: Eq + Hash,
K::Generator: Send + Sync,
V::Generator: Send + Sync,
{
type Generator = HashMapGenerator<K::Generator, V::Generator, K, V>;
fn default_generator() -> Self::Generator {
hashmaps(K::default_generator(), V::default_generator())
}
}
#[macro_export]
macro_rules! derive_generator {
($struct_name:ident { $($field_name:ident : $field_type:ty),* $(,)? }) => {
const _: () = {
$crate::paste::paste! {
pub struct [<$struct_name Generator>]<'a> {
$(
$field_name: $crate::generators::BoxedGenerator<'a, $field_type>,
)*
}
impl<'a> [<$struct_name Generator>]<'a> {
pub fn new() -> Self
where
$($field_type: $crate::generators::DefaultGenerator,)*
$(<$field_type as $crate::generators::DefaultGenerator>::Generator: Send + Sync + 'a,)*
{
use $crate::generators::{DefaultGenerator, Generator};
Self {
$($field_name: <$field_type as DefaultGenerator>::default_generator().boxed(),)*
}
}
$(
pub fn $field_name<G>(mut self, generator: G) -> Self
where
G: $crate::generators::Generator<$field_type> + Send + Sync + 'a,
{
use $crate::generators::Generator;
self.$field_name = generator.boxed();
self
}
)*
}
impl<'a> Default for [<$struct_name Generator>]<'a>
where
$($field_type: $crate::generators::DefaultGenerator,)*
$(<$field_type as $crate::generators::DefaultGenerator>::Generator: Send + Sync + 'a,)*
{
fn default() -> Self {
Self::new()
}
}
impl<'a> $crate::generators::Generator<$struct_name> for [<$struct_name Generator>]<'a> {
fn do_draw(&self, __data: &$crate::TestCase) -> $struct_name {
use $crate::generators::Generator;
$struct_name {
$($field_name: self.$field_name.do_draw(__data),)*
}
}
}
impl $crate::generators::DefaultGenerator for $struct_name
where
$($field_type: $crate::generators::DefaultGenerator,)*
$(<$field_type as $crate::generators::DefaultGenerator>::Generator: Send + Sync + 'static,)*
{
type Generator = [<$struct_name Generator>]<'static>;
fn default_generator() -> Self::Generator {
[<$struct_name Generator>]::new()
}
}
}
};
};
}