hegel/generators/
compose.rs1use super::{Generator, TestCase};
2use std::marker::PhantomData;
3
4#[doc(hidden)]
6pub struct ComposedGenerator<T, F> {
7 f: F,
8 _phantom: PhantomData<fn() -> T>,
9}
10
11impl<T, F> ComposedGenerator<T, F>
12where
13 F: Fn(TestCase) -> T,
14{
15 pub fn new(f: F) -> Self {
17 ComposedGenerator {
18 f,
19 _phantom: PhantomData,
20 }
21 }
22}
23
24impl<T, F> Generator<T> for ComposedGenerator<T, F>
25where
26 F: Fn(TestCase) -> T + Send + Sync,
27{
28 fn do_draw(&self, tc: &TestCase) -> T {
29 (self.f)(tc.clone())
30 }
31}
32
33#[doc(hidden)]
35pub const fn fnv1a_hash(bytes: &[u8]) -> u64 {
37 const FNV_OFFSET: u64 = 0xcbf29ce484222325;
39 const FNV_PRIME: u64 = 0x100000001b3;
40 let mut hash = FNV_OFFSET;
42 let mut i = 0;
43 while i < bytes.len() {
44 hash ^= bytes[i] as u64;
45 hash = hash.wrapping_mul(FNV_PRIME);
46 i += 1;
47 }
48 hash
49 }
51
52#[macro_export]
73macro_rules! compose {
74 (|$tc:ident| { $($body:tt)* }) => {{
75 const LABEL: u64 = $crate::generators::fnv1a_hash(stringify!($($body)*).as_bytes());
76 $crate::generators::ComposedGenerator::new(move |$tc: $crate::TestCase| {
77 $tc.start_span(LABEL);
78 let __result = { $($body)* };
79 $tc.stop_span(false);
80 __result
81 })
82 }};
83}