Skip to main content

hegel/generators/
tuples.rs

1use super::{DefaultGenerator, Generator, TestCase, labels};
2use std::marker::PhantomData;
3
4/// Creates a tuple generator from 0–12 component generators.
5///
6/// # Examples
7///
8/// ```no_run
9/// use hegel::generators as gs;
10/// use hegel::tuples;
11///
12/// // 0-tuple (unit)
13/// let gen0 = tuples!();
14///
15/// // 1-tuple
16/// let gen1 = tuples!(gs::integers::<i32>());
17///
18/// // 2-tuple
19/// let gen2 = tuples!(gs::integers::<i32>(), gs::booleans());
20///
21/// // 3-tuple
22/// let gen3 = tuples!(gs::integers::<i32>(), gs::booleans(), gs::text());
23/// ```
24#[macro_export]
25macro_rules! tuples {
26    () => {
27        $crate::generators::tuples0()
28    };
29    ($g1:expr $(,)?) => {
30        $crate::generators::tuples1($g1)
31    };
32    ($g1:expr, $g2:expr $(,)?) => {
33        $crate::generators::tuples2($g1, $g2)
34    };
35    ($g1:expr, $g2:expr, $g3:expr $(,)?) => {
36        $crate::generators::tuples3($g1, $g2, $g3)
37    };
38    ($g1:expr, $g2:expr, $g3:expr, $g4:expr $(,)?) => {
39        $crate::generators::tuples4($g1, $g2, $g3, $g4)
40    };
41    ($g1:expr, $g2:expr, $g3:expr, $g4:expr, $g5:expr $(,)?) => {
42        $crate::generators::tuples5($g1, $g2, $g3, $g4, $g5)
43    };
44    ($g1:expr, $g2:expr, $g3:expr, $g4:expr, $g5:expr, $g6:expr $(,)?) => {
45        $crate::generators::tuples6($g1, $g2, $g3, $g4, $g5, $g6)
46    };
47    ($g1:expr, $g2:expr, $g3:expr, $g4:expr, $g5:expr, $g6:expr, $g7:expr $(,)?) => {
48        $crate::generators::tuples7($g1, $g2, $g3, $g4, $g5, $g6, $g7)
49    };
50    ($g1:expr, $g2:expr, $g3:expr, $g4:expr, $g5:expr, $g6:expr, $g7:expr, $g8:expr $(,)?) => {
51        $crate::generators::tuples8($g1, $g2, $g3, $g4, $g5, $g6, $g7, $g8)
52    };
53    ($g1:expr, $g2:expr, $g3:expr, $g4:expr, $g5:expr, $g6:expr, $g7:expr, $g8:expr, $g9:expr $(,)?) => {
54        $crate::generators::tuples9($g1, $g2, $g3, $g4, $g5, $g6, $g7, $g8, $g9)
55    };
56    ($g1:expr, $g2:expr, $g3:expr, $g4:expr, $g5:expr, $g6:expr, $g7:expr, $g8:expr, $g9:expr, $g10:expr $(,)?) => {
57        $crate::generators::tuples10($g1, $g2, $g3, $g4, $g5, $g6, $g7, $g8, $g9, $g10)
58    };
59    ($g1:expr, $g2:expr, $g3:expr, $g4:expr, $g5:expr, $g6:expr, $g7:expr, $g8:expr, $g9:expr, $g10:expr, $g11:expr $(,)?) => {
60        $crate::generators::tuples11($g1, $g2, $g3, $g4, $g5, $g6, $g7, $g8, $g9, $g10, $g11)
61    };
62    ($g1:expr, $g2:expr, $g3:expr, $g4:expr, $g5:expr, $g6:expr, $g7:expr, $g8:expr, $g9:expr, $g10:expr, $g11:expr, $g12:expr $(,)?) => {
63        $crate::generators::tuples12(
64            $g1, $g2, $g3, $g4, $g5, $g6, $g7, $g8, $g9, $g10, $g11, $g12,
65        )
66    };
67}
68
69macro_rules! impl_tuple {
70    ($name:ident, $fn_name:ident, $(($idx:tt, $field:ident, $G:ident, $T:ident)),+) => {
71        pub struct $name<$($G,)+ $($T,)+> {
72            $($field: $G,)+
73            _phantom: PhantomData<fn($($T,)+)>,
74        }
75
76        impl<$($T,)+ $($G,)+> Generator<($($T,)+)> for $name<$($G,)+ $($T,)+>
77        where
78            $($G: Generator<$T>,)+
79        {
80            fn do_draw(&self, tc: &TestCase) -> ($($T,)+) {
81                tc.start_span(labels::TUPLE);
82                let result = ($(self.$field.do_draw(tc),)+);
83                tc.stop_span(false);
84                result
85            }
86        }
87
88        #[doc(hidden)]
89        #[allow(clippy::too_many_arguments)]
90        pub fn $fn_name<$($T,)+ $($G: Generator<$T>,)+>(
91            $($field: $G,)+
92        ) -> $name<$($G,)+ $($T,)+> {
93            $name {
94                $($field,)+
95                _phantom: PhantomData,
96            }
97        }
98
99        impl<$($T: DefaultGenerator + 'static,)+> DefaultGenerator for ($($T,)+)
100        where
101            $(<$T as DefaultGenerator>::Generator: Send + Sync,)+
102        {
103            type Generator = $name<$(<$T as DefaultGenerator>::Generator,)+ $($T,)+>;
104            fn default_generator() -> Self::Generator {
105                $fn_name($(<$T>::default_generator(),)+)
106            }
107        }
108    };
109}
110
111/// Generator for the unit type `()`. Created by [`tuples0()`].
112pub struct Tuple0Generator;
113
114impl Generator<()> for Tuple0Generator {
115    fn do_draw(&self, _tc: &TestCase) {}
116}
117
118#[doc(hidden)]
119pub fn tuples0() -> Tuple0Generator {
120    Tuple0Generator
121}
122
123impl DefaultGenerator for () {
124    type Generator = Tuple0Generator;
125    fn default_generator() -> Self::Generator {
126        tuples0()
127    }
128}
129
130impl_tuple!(Tuple1Generator, tuples1, (0, gen1, G1, T1));
131impl_tuple!(
132    Tuple2Generator,
133    tuples2,
134    (0, gen1, G1, T1),
135    (1, gen2, G2, T2)
136);
137impl_tuple!(
138    Tuple3Generator,
139    tuples3,
140    (0, gen1, G1, T1),
141    (1, gen2, G2, T2),
142    (2, gen3, G3, T3)
143);
144impl_tuple!(
145    Tuple4Generator,
146    tuples4,
147    (0, gen1, G1, T1),
148    (1, gen2, G2, T2),
149    (2, gen3, G3, T3),
150    (3, gen4, G4, T4)
151);
152impl_tuple!(
153    Tuple5Generator,
154    tuples5,
155    (0, gen1, G1, T1),
156    (1, gen2, G2, T2),
157    (2, gen3, G3, T3),
158    (3, gen4, G4, T4),
159    (4, gen5, G5, T5)
160);
161impl_tuple!(
162    Tuple6Generator,
163    tuples6,
164    (0, gen1, G1, T1),
165    (1, gen2, G2, T2),
166    (2, gen3, G3, T3),
167    (3, gen4, G4, T4),
168    (4, gen5, G5, T5),
169    (5, gen6, G6, T6)
170);
171impl_tuple!(
172    Tuple7Generator,
173    tuples7,
174    (0, gen1, G1, T1),
175    (1, gen2, G2, T2),
176    (2, gen3, G3, T3),
177    (3, gen4, G4, T4),
178    (4, gen5, G5, T5),
179    (5, gen6, G6, T6),
180    (6, gen7, G7, T7)
181);
182impl_tuple!(
183    Tuple8Generator,
184    tuples8,
185    (0, gen1, G1, T1),
186    (1, gen2, G2, T2),
187    (2, gen3, G3, T3),
188    (3, gen4, G4, T4),
189    (4, gen5, G5, T5),
190    (5, gen6, G6, T6),
191    (6, gen7, G7, T7),
192    (7, gen8, G8, T8)
193);
194impl_tuple!(
195    Tuple9Generator,
196    tuples9,
197    (0, gen1, G1, T1),
198    (1, gen2, G2, T2),
199    (2, gen3, G3, T3),
200    (3, gen4, G4, T4),
201    (4, gen5, G5, T5),
202    (5, gen6, G6, T6),
203    (6, gen7, G7, T7),
204    (7, gen8, G8, T8),
205    (8, gen9, G9, T9)
206);
207impl_tuple!(
208    Tuple10Generator,
209    tuples10,
210    (0, gen1, G1, T1),
211    (1, gen2, G2, T2),
212    (2, gen3, G3, T3),
213    (3, gen4, G4, T4),
214    (4, gen5, G5, T5),
215    (5, gen6, G6, T6),
216    (6, gen7, G7, T7),
217    (7, gen8, G8, T8),
218    (8, gen9, G9, T9),
219    (9, gen10, G10, T10)
220);
221impl_tuple!(
222    Tuple11Generator,
223    tuples11,
224    (0, gen1, G1, T1),
225    (1, gen2, G2, T2),
226    (2, gen3, G3, T3),
227    (3, gen4, G4, T4),
228    (4, gen5, G5, T5),
229    (5, gen6, G6, T6),
230    (6, gen7, G7, T7),
231    (7, gen8, G8, T8),
232    (8, gen9, G9, T9),
233    (9, gen10, G10, T10),
234    (10, gen11, G11, T11)
235);
236impl_tuple!(
237    Tuple12Generator,
238    tuples12,
239    (0, gen1, G1, T1),
240    (1, gen2, G2, T2),
241    (2, gen3, G3, T3),
242    (3, gen4, G4, T4),
243    (4, gen5, G5, T5),
244    (5, gen6, G6, T6),
245    (6, gen7, G7, T7),
246    (7, gen8, G8, T8),
247    (8, gen9, G9, T9),
248    (9, gen10, G10, T10),
249    (10, gen11, G11, T11),
250    (11, gen12, G12, T12)
251);