bolero_generator/
result.rs

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}