1use crate::{Driver, TypeGenerator, TypeGeneratorWithParams, TypeValueGenerator, ValueGenerator};
2
3#[cfg(feature = "either")]
4use either::Either;
5
6macro_rules! impl_either {
7 (
8 $generator:ident,
9 $ty:ident,
10 $A:ident,
11 $with_a:ident,
12 $map_a:ident,
13 $B:ident,
14 $with_b:ident,
15 $map_b:ident
16 ) => {
17 #[derive(Debug, Clone)]
18 pub struct $generator<$A, $B> {
19 a: $A,
20 b: $B,
21 }
22
23 impl<$A: ValueGenerator, $B: ValueGenerator> $generator<$A, $B> {
24 pub fn $with_a<Gen: ValueGenerator<Output = $A::Output>>(
25 self,
26 produce: Gen,
27 ) -> $generator<Gen, $B> {
28 $generator {
29 a: produce,
30 b: self.b,
31 }
32 }
33
34 pub fn $map_a<Gen: ValueGenerator<Output = $A::Output>, F: Fn($A) -> Gen>(
35 self,
36 map: F,
37 ) -> $generator<Gen, $B> {
38 $generator {
39 a: map(self.a),
40 b: self.b,
41 }
42 }
43
44 pub fn $with_b<Gen: ValueGenerator<Output = $B::Output>>(
45 self,
46 produce: Gen,
47 ) -> $generator<$A, Gen> {
48 $generator {
49 a: self.a,
50 b: produce,
51 }
52 }
53
54 pub fn $map_b<Gen: ValueGenerator<Output = $B::Output>, F: Fn($B) -> Gen>(
55 self,
56 map: F,
57 ) -> $generator<$A, Gen> {
58 $generator {
59 a: self.a,
60 b: map(self.b),
61 }
62 }
63 }
64
65 impl<$A: ValueGenerator, $B: ValueGenerator> ValueGenerator for $generator<$A, $B> {
66 type Output = $ty<$A::Output, $B::Output>;
67
68 #[inline]
69 fn generate<D: Driver>(&self, driver: &mut D) -> Option<Self::Output> {
70 driver.enter_sum::<Self::Output, _, _>(
71 Some(&[stringify!($A), stringify!($B)]),
72 2,
73 0,
74 |driver, idx| {
75 if idx == 0 {
76 Some($ty::$A(self.a.generate(driver)?))
77 } else {
78 Some($ty::$B(self.b.generate(driver)?))
79 }
80 },
81 )
82 }
83
84 #[inline]
85 fn mutate<D: Driver>(&self, driver: &mut D, value: &mut Self::Output) -> Option<()> {
86 driver.enter_sum::<Self::Output, _, _>(
87 Some(&[stringify!($A), stringify!($B)]),
88 2,
89 0,
90 |driver, new_selection| {
91 #[allow(clippy::redundant_pattern_matching)]
92 let prev_selection = match value {
93 $ty::$A(_) => 0,
94 $ty::$B(_) => 1,
95 };
96
97 if prev_selection == new_selection {
98 match value {
99 $ty::$A(value) => self.a.mutate(driver, value),
100 $ty::$B(value) => self.b.mutate(driver, value),
101 }
102 } else {
103 let next = if new_selection == 0 {
104 $ty::$A(self.a.generate(driver)?)
105 } else {
106 $ty::$B(self.b.generate(driver)?)
107 };
108 match core::mem::replace(value, next) {
109 $ty::$A(v) => self.a.driver_cache(driver, v),
110 $ty::$B(v) => self.b.driver_cache(driver, v),
111 }
112 Some(())
113 }
114 },
115 )
116 }
117
118 #[inline]
119 fn driver_cache<D: Driver>(&self, driver: &mut D, value: Self::Output) {
120 match value {
121 $ty::$A(v) => self.a.driver_cache(driver, v),
122 $ty::$B(v) => self.b.driver_cache(driver, v),
123 }
124 }
125 }
126
127 impl<$A: TypeGenerator, $B: TypeGenerator> TypeGenerator for $ty<$A, $B> {
128 #[inline]
129 fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
130 crate::produce_with::<Self>().generate(driver)
131 }
132
133 #[inline]
134 fn mutate<D: Driver>(&mut self, driver: &mut D) -> Option<()> {
135 crate::produce_with::<Self>().mutate(driver, self)
136 }
137
138 #[inline]
139 fn driver_cache<D: Driver>(self, driver: &mut D) {
140 crate::produce_with::<Self>().driver_cache(driver, self)
141 }
142 }
143
144 impl<$A: TypeGenerator, $B: TypeGenerator> TypeGeneratorWithParams for $ty<$A, $B> {
145 type Output = $generator<TypeValueGenerator<$A>, TypeValueGenerator<$B>>;
146
147 fn gen_with() -> Self::Output {
148 $generator {
149 a: Default::default(),
150 b: Default::default(),
151 }
152 }
153 }
154 };
155}
156
157impl_either!(ResultGenerator, Result, Ok, ok, map_ok, Err, err, map_err);
158
159#[cfg(feature = "either")]
160impl_either!(
161 EitherGenerator,
162 Either,
163 Left,
164 left,
165 map_left,
166 Right,
167 right,
168 map_right
169);
170
171pub struct OptionGenerator<V> {
172 value: V,
173}
174
175impl<V: ValueGenerator> OptionGenerator<V> {
176 pub fn value<Gen: ValueGenerator<Output = V::Output>>(
177 self,
178 value: Gen,
179 ) -> OptionGenerator<Gen> {
180 OptionGenerator { value }
181 }
182
183 pub fn map_value<Gen: ValueGenerator<Output = V::Output>, F: Fn(V) -> Gen>(
184 self,
185 map: F,
186 ) -> OptionGenerator<Gen> {
187 OptionGenerator {
188 value: map(self.value),
189 }
190 }
191}
192
193impl<V: ValueGenerator> ValueGenerator for OptionGenerator<V> {
194 type Output = Option<V::Output>;
195
196 #[inline]
197 fn generate<D: Driver>(&self, driver: &mut D) -> Option<Self::Output> {
198 driver.enter_sum::<Self::Output, _, _>(Some(&["None", "Some"]), 2, 0, |driver, idx| {
199 if idx == 0 {
200 Some(None)
201 } else {
202 Some(Some(self.value.generate(driver)?))
203 }
204 })
205 }
206
207 #[inline]
208 fn mutate<D: Driver>(&self, driver: &mut D, value: &mut Self::Output) -> Option<()> {
209 driver.enter_sum::<Self::Output, _, _>(
210 Some(&["None", "Some"]),
211 2,
212 0,
213 |driver, new_selection| {
214 let prev_selection = usize::from(value.is_some());
215
216 if prev_selection == new_selection {
217 match value {
218 Some(value) => self.value.mutate(driver, value),
219 None => Some(()),
220 }
221 } else {
222 let next = if new_selection == 1 {
223 Some(self.value.generate(driver)?)
224 } else {
225 None
226 };
227 if let Some(prev) = core::mem::replace(value, next) {
228 self.value.driver_cache(driver, prev);
229 }
230 Some(())
231 }
232 },
233 )
234 }
235}
236
237impl<V: TypeGenerator> TypeGenerator for Option<V> {
238 #[inline]
239 fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
240 crate::produce_with::<Self>().generate(driver)
241 }
242
243 #[inline]
244 fn mutate<D: Driver>(&mut self, driver: &mut D) -> Option<()> {
245 crate::produce_with::<Self>().mutate(driver, self)
246 }
247
248 #[inline]
249 fn driver_cache<D: Driver>(self, driver: &mut D) {
250 crate::produce_with::<Self>().driver_cache(driver, self)
251 }
252}
253
254impl<V: TypeGenerator> TypeGeneratorWithParams for Option<V> {
255 type Output = OptionGenerator<TypeValueGenerator<V>>;
256
257 fn gen_with() -> Self::Output {
258 OptionGenerator {
259 value: Default::default(),
260 }
261 }
262}
263
264#[test]
265fn result_test() {
266 let _ = generator_test!(produce::<Result<u8, u8>>());
267}
268
269#[test]
270fn option_test() {
271 let _ = generator_test!(produce::<Option<u8>>());
272}