1use crate::test_case::{TestCase, invalid_argument, labels};
2use std::marker::PhantomData;
3use std::sync::Arc;
4
5pub trait Generator<T> {
10 #[doc(hidden)]
12 fn do_draw(&self, tc: &TestCase) -> T;
13
14 fn map<U, F>(self, f: F) -> Mapped<T, U, F, Self>
25 where
26 Self: Sized,
27 F: Fn(T) -> U + Send + Sync,
28 {
29 Mapped {
30 source: self,
31 f: Arc::new(f),
32 _phantom: PhantomData,
33 }
34 }
35
36 fn flat_map<U, G, F>(self, f: F) -> FlatMapped<T, U, G, F, Self>
52 where
53 Self: Sized,
54 G: Generator<U>,
55 F: Fn(T) -> G + Send + Sync,
56 {
57 FlatMapped {
58 source: self,
59 f,
60 _phantom: PhantomData,
61 }
62 }
63
64 fn filter<F>(self, predicate: F) -> Filtered<T, F, Self>
77 where
78 Self: Sized,
79 F: Fn(&T) -> bool + Send + Sync,
80 {
81 Filtered {
82 source: self,
83 predicate,
84 enumerated: std::sync::OnceLock::new(),
85 _phantom: PhantomData,
86 }
87 }
88
89 #[doc(hidden)]
95 fn enumerate_values(&self) -> Option<Vec<T>> {
96 None
97 }
98
99 fn boxed<'a>(self) -> BoxedGenerator<'a, T>
119 where
120 Self: Sized + Send + Sync + 'a,
121 {
122 BoxedGenerator {
123 inner: Arc::new(self),
124 }
125 }
126}
127
128impl<T, G: Generator<T>> Generator<T> for &G {
129 fn do_draw(&self, tc: &TestCase) -> T {
130 (*self).do_draw(tc)
131 }
132
133 fn enumerate_values(&self) -> Option<Vec<T>> {
134 (*self).enumerate_values()
135 }
136}
137
138pub struct Mapped<T, U, F, G> {
140 source: G,
141 f: Arc<F>,
142 _phantom: PhantomData<fn(T) -> U>,
143}
144
145impl<T, U, F, G> Generator<U> for Mapped<T, U, F, G>
146where
147 G: Generator<T>,
148 F: Fn(T) -> U + Send + Sync,
149{
150 fn do_draw(&self, tc: &TestCase) -> U {
151 tc.start_span(labels::MAPPED);
152 let result = (self.f)(self.source.do_draw(tc));
153 tc.stop_span(false);
154 result
155 }
156
157 fn enumerate_values(&self) -> Option<Vec<U>> {
158 self.source
159 .enumerate_values()
160 .map(|vals| vals.into_iter().map(|v| (self.f)(v)).collect())
161 }
162}
163
164pub struct FlatMapped<T, U, G2, F, G1> {
166 source: G1,
167 f: F,
168 _phantom: PhantomData<fn(T) -> (U, G2)>,
169}
170
171impl<T, U, G2, F, G1> Generator<U> for FlatMapped<T, U, G2, F, G1>
172where
173 G1: Generator<T>,
174 G2: Generator<U>,
175 F: Fn(T) -> G2 + Send + Sync,
176{
177 fn do_draw(&self, tc: &TestCase) -> U {
178 tc.start_span(labels::FLAT_MAP);
179 let intermediate = self.source.do_draw(tc);
180 let next_gen = (self.f)(intermediate);
181 let result = next_gen.do_draw(tc);
182 tc.stop_span(false);
183 result
184 }
185}
186
187pub struct Filtered<T, F, G> {
189 source: G,
190 predicate: F,
191 enumerated: std::sync::OnceLock<Option<Vec<T>>>,
196 _phantom: PhantomData<fn() -> T>,
197}
198
199impl<T, F, G> Filtered<T, F, G>
200where
201 T: Clone + Send + Sync,
202 G: Generator<T>,
203 F: Fn(&T) -> bool + Send + Sync,
204{
205 fn enumerated(&self) -> &Option<Vec<T>> {
206 self.enumerated.get_or_init(|| {
207 self.source
208 .enumerate_values()
209 .map(|vals| vals.into_iter().filter(|v| (self.predicate)(v)).collect())
210 })
211 }
212}
213
214impl<T, F, G> Generator<T> for Filtered<T, F, G>
215where
216 T: Clone + Send + Sync,
217 G: Generator<T>,
218 F: Fn(&T) -> bool + Send + Sync,
219{
220 fn do_draw(&self, tc: &TestCase) -> T {
221 if let Some(valid) = self.enumerated() {
222 if valid.is_empty() {
223 invalid_argument!(
224 "Unsatisfiable filter: all values from the source generator \
225 are rejected by the filter predicate"
226 );
227 }
228 let index = tc.generate_integer_i64(0, valid.len() as i64 - 1) as usize;
229 return valid[index].clone();
230 }
231 for _ in 0..3 {
232 tc.start_span(labels::FILTER);
233 let value = self.source.do_draw(tc);
234 if (self.predicate)(&value) {
235 tc.stop_span(false);
236 return value;
237 }
238 tc.stop_span(true);
239 }
240 tc.assume(false);
241 unreachable!()
242 }
243
244 fn enumerate_values(&self) -> Option<Vec<T>> {
245 self.enumerated().clone()
246 }
247}
248
249pub struct BoxedGenerator<'a, T> {
251 pub(super) inner: Arc<dyn Generator<T> + Send + Sync + 'a>,
252}
253
254impl<T> Clone for BoxedGenerator<'_, T> {
255 fn clone(&self) -> Self {
256 BoxedGenerator {
257 inner: Arc::clone(&self.inner),
258 }
259 }
260}
261
262impl<T> Generator<T> for BoxedGenerator<'_, T> {
263 fn do_draw(&self, tc: &TestCase) -> T {
264 self.inner.do_draw(tc)
265 }
266
267 fn enumerate_values(&self) -> Option<Vec<T>> {
268 self.inner.enumerate_values()
269 }
270
271 fn boxed<'b>(self) -> BoxedGenerator<'b, T>
272 where
273 Self: Sized + Send + Sync + 'b,
274 {
275 BoxedGenerator { inner: self.inner }
276 }
277}