bolero_generator/
range.rs

1use crate::{Driver, TypeGenerator, TypeGeneratorWithParams, TypeValueGenerator, ValueGenerator};
2
3macro_rules! range_generator {
4    ($ty:ident, $generator:ident, | $start:ident, $end:ident | $new:expr) => {
5        pub struct $generator<Start, End> {
6            start: Start,
7            end: End,
8        }
9
10        impl<Start, End, T> $generator<Start, End>
11        where
12            Start: ValueGenerator<Output = T>,
13            End: ValueGenerator<Output = T>,
14        {
15            pub fn start<NewS: ValueGenerator<Output = T>>(
16                self,
17                start: NewS,
18            ) -> $generator<NewS, End> {
19                $generator {
20                    start,
21                    end: self.end,
22                }
23            }
24
25            pub fn map_start<NewS: ValueGenerator<Output = T>, F: Fn(Start) -> NewS>(
26                self,
27                map: F,
28            ) -> $generator<NewS, End> {
29                $generator {
30                    start: map(self.start),
31                    end: self.end,
32                }
33            }
34
35            pub fn end<NewE: ValueGenerator<Output = T>>(
36                self,
37                end: NewE,
38            ) -> $generator<Start, NewE> {
39                $generator {
40                    start: self.start,
41                    end,
42                }
43            }
44
45            pub fn map_end<NewE: ValueGenerator<Output = T>, F: Fn(End) -> NewE>(
46                self,
47                map: F,
48            ) -> $generator<Start, NewE> {
49                $generator {
50                    start: self.start,
51                    end: map(self.end),
52                }
53            }
54        }
55
56        impl<Start, End, T> ValueGenerator for $generator<Start, End>
57        where
58            Start: ValueGenerator<Output = T>,
59            End: ValueGenerator<Output = T>,
60            T: 'static,
61        {
62            type Output = core::ops::$ty<T>;
63
64            fn generate<D: Driver>(&self, driver: &mut D) -> Option<Self::Output> {
65                driver.enter_product::<Self::Output, _, _>(|driver| {
66                    let $start = self.start.generate(driver)?;
67                    let $end = self.end.generate(driver)?;
68                    Some($new)
69                })
70            }
71        }
72
73        impl<T: TypeGenerator> TypeGenerator for core::ops::$ty<T> {
74            fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
75                driver.enter_product::<Self, _, _>(|driver| {
76                    let $start = driver.produce()?;
77                    let $end = driver.produce()?;
78                    Some($new)
79                })
80            }
81        }
82
83        impl<T: TypeGenerator> TypeGeneratorWithParams for core::ops::$ty<T> {
84            type Output = $generator<TypeValueGenerator<T>, TypeValueGenerator<T>>;
85
86            fn gen_with() -> Self::Output {
87                $generator {
88                    start: Default::default(),
89                    end: Default::default(),
90                }
91            }
92        }
93    };
94}
95
96range_generator!(Range, RangeGenerator, |start, end| start..end);
97range_generator!(RangeInclusive, RangeInclusiveGenerator, |start, end| start
98    ..=end);
99
100#[test]
101fn range_type_test() {
102    use core::ops::Range;
103
104    let _ = generator_test!(produce::<Range<usize>>());
105}
106
107#[test]
108fn range_with_test() {
109    use core::ops::Range;
110
111    let _ = generator_test!(produce::<Range<usize>>().with().start(4..6).end(6..10));
112}
113
114#[test]
115fn range_gen_test() {
116    let _ = generator_test!(0usize..10);
117}