use super::{Generator, TestCase};
use std::marker::PhantomData;
#[doc(hidden)]
pub struct ComposedGenerator<T, F> {
f: F,
_phantom: PhantomData<fn() -> T>,
}
impl<T, F> ComposedGenerator<T, F>
where
F: Fn(TestCase) -> T,
{
pub fn new(f: F) -> Self {
ComposedGenerator {
f,
_phantom: PhantomData,
}
}
}
impl<T, F> Generator<T> for ComposedGenerator<T, F>
where
F: Fn(TestCase) -> T + Send + Sync,
{
fn do_draw(&self, tc: &TestCase) -> T {
(self.f)(tc.clone())
}
}
#[doc(hidden)]
pub const fn fnv1a_hash(bytes: &[u8]) -> u64 {
const FNV_OFFSET: u64 = 0xcbf29ce484222325;
const FNV_PRIME: u64 = 0x100000001b3;
let mut hash = FNV_OFFSET;
let mut i = 0;
while i < bytes.len() {
hash ^= bytes[i] as u64;
hash = hash.wrapping_mul(FNV_PRIME);
i += 1;
}
hash
}
#[macro_export]
macro_rules! compose {
(|$tc:ident| { $($body:tt)* }) => {{
const LABEL: u64 = $crate::generators::fnv1a_hash(stringify!($($body)*).as_bytes());
$crate::generators::ComposedGenerator::new(move |$tc: $crate::TestCase| {
$tc.start_span(LABEL);
let __result = { $($body)* };
$tc.stop_span(false);
__result
})
}};
}