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 {
36 const FNV_OFFSET: u64 = 0xcbf29ce484222325;
37 const FNV_PRIME: u64 = 0x100000001b3;
38 let mut hash = FNV_OFFSET;
39 let mut i = 0;
40 while i < bytes.len() {
41 hash ^= bytes[i] as u64;
42 hash = hash.wrapping_mul(FNV_PRIME);
43 i += 1;
44 }
45 hash
46}
47
48#[macro_export]
69macro_rules! compose {
70 (|$tc:ident| { $($body:tt)* }) => {{
71 const LABEL: u64 = $crate::generators::fnv1a_hash(stringify!($($body)*).as_bytes());
72 $crate::generators::ComposedGenerator::new(move |$tc: $crate::TestCase| {
73 $tc.start_span(LABEL);
74 let __result = { $($body)* };
75 $tc.stop_span(false);
76 __result
77 })
78 }};
79}