bolero_generator/
driver.rs

1use crate::{
2    uniform::{FillBytes, Uniform},
3    TypeGenerator, ValueGenerator,
4};
5use core::ops::Bound;
6use rand_core::TryRngCore;
7
8#[macro_use]
9mod macros;
10
11pub mod bytes;
12#[cfg(feature = "alloc")]
13pub mod cache;
14#[cfg(feature = "alloc")]
15pub mod exhaustive;
16pub mod object;
17mod options;
18mod rng;
19
20pub use bytes::ByteSliceDriver;
21pub use options::Options;
22pub use rng::Rng;
23
24macro_rules! gen_method {
25    ($name:ident, $constant:ident, $ty:ty) => {
26        fn $name(&mut self, min: Bound<&$ty>, max: Bound<&$ty>) -> Option<$ty>;
27
28        #[inline(always)]
29        fn $constant(&mut self, value: $ty) -> Option<$ty> {
30            Some(value)
31        }
32    };
33}
34
35/// Trait for driving the generation of a value
36///
37/// In a test engine, this is typically backed by
38/// a byte slice, but other drivers can be used instead, e.g.
39/// an RNG implementation.
40pub trait Driver: Sized {
41    /// Generate a value with type `T`
42    #[inline(always)]
43    fn produce<T: TypeGenerator>(&mut self) -> Option<T> {
44        T::generate(self)
45    }
46
47    #[deprecated = "Use `produce` instead (`gen` conflicts with edition2024)"]
48    #[inline(always)]
49    fn gen<T: TypeGenerator>(&mut self) -> Option<T> {
50        self.produce()
51    }
52
53    #[inline]
54    fn depth_guard<F, R>(&mut self, f: F) -> Option<R>
55    where
56        F: FnOnce(&mut Self) -> Option<R>,
57    {
58        let depth = self.depth();
59        if depth == self.max_depth() {
60            return None;
61        }
62
63        let new_depth = depth + 1;
64        self.set_depth(new_depth);
65        let value = f(self);
66        self.set_depth(depth);
67
68        value
69    }
70
71    fn depth(&self) -> usize;
72
73    fn set_depth(&mut self, depth: usize);
74
75    fn max_depth(&self) -> usize;
76
77    #[inline(always)]
78    fn enter_product<Output, F, Ret>(&mut self, mut f: F) -> Option<Ret>
79    where
80        Output: 'static,
81        F: FnMut(&mut Self) -> Option<Ret>,
82    {
83        f(self)
84    }
85
86    #[inline(always)]
87    fn enter_sum<Output, F, Ret>(
88        &mut self,
89        element_names: Option<&'static [&'static str]>,
90        elements: usize,
91        base_case: usize,
92        mut f: F,
93    ) -> Option<Ret>
94    where
95        Output: 'static,
96        F: FnMut(&mut Self, usize) -> Option<Ret>,
97    {
98        let _ = element_names;
99        let idx = self.gen_variant(elements, base_case)?;
100        f(self, idx)
101    }
102
103    #[inline(always)]
104    fn enter_list<Output, F, Len, Ret>(&mut self, lens: &Len, mut f: F) -> Option<Ret>
105    where
106        Output: 'static,
107        F: FnMut(&mut Self, usize) -> Option<Ret>,
108        Len: ValueGenerator<Output = usize>,
109    {
110        self.depth_guard(|driver| {
111            let len = lens.generate(driver)?;
112            f(driver, len)
113        })
114    }
115
116    #[inline(always)]
117    fn enter_combinator<Output, F, Ret>(&mut self, mut f: F) -> Option<Ret>
118    where
119        Output: 'static,
120        F: FnMut(&mut Self) -> Option<Ret>,
121    {
122        f(self)
123    }
124
125    fn gen_variant(&mut self, variants: usize, base_case: usize) -> Option<usize>;
126
127    gen_method!(gen_u8, gen_u8_constant, u8);
128    gen_method!(gen_i8, gen_i8_constant, i8);
129    gen_method!(gen_u16, gen_u16_constant, u16);
130    gen_method!(gen_i16, gen_i16_constant, i16);
131    gen_method!(gen_u32, gen_u32_constant, u32);
132    gen_method!(gen_i32, gen_i32_constant, i32);
133    gen_method!(gen_u64, gen_u64_constant, u64);
134    gen_method!(gen_i64, gen_i64_constant, i64);
135    gen_method!(gen_u128, gen_u128_constant, u128);
136    gen_method!(gen_i128, gen_i128_constant, i128);
137    gen_method!(gen_usize, gen_usize_constant, usize);
138    gen_method!(gen_isize, gen_isize_constant, isize);
139    gen_method!(gen_f32, gen_f32_constant, f32);
140    gen_method!(gen_f64, gen_f64_constant, f64);
141    gen_method!(gen_char, gen_char_constant, char);
142
143    fn gen_bool(&mut self, probability: Option<f32>) -> Option<bool>;
144
145    /// Generate a value from bytes off this generator
146    ///
147    /// `len` is the size of the slice that should be passed to `gen`. The range's minimal size
148    /// is the minimal amount of bytes needed to properly generate an input. The range's maximal
149    /// value should be so that every `T` can be generated by `gen` from a slice of this length.
150    ///
151    /// `gen` is the function that actually does the generation. It takes as input the byte slice,
152    /// and returns either `None` (if not enough bytes were provided to build a `T`, this can
153    /// happen even with a slice of maximum length but should happen as rarely as possible), or
154    /// a `Some` value if it could generate a `T`. In this case, it also returns the number of
155    /// bytes that were actually consumed from the slice.
156    ///
157    /// Note that `gen` may be called multiple times with increasing slice lengths, eg. if the
158    /// driver is in forced mode.
159    fn gen_from_bytes<Hint, Gen, T>(&mut self, hint: Hint, produce: Gen) -> Option<T>
160    where
161        Hint: FnOnce() -> (usize, Option<usize>),
162        Gen: FnMut(&[u8]) -> Option<(usize, T)>;
163
164    #[inline(always)]
165    fn cache_put<T: 'static>(&mut self, value: T) {
166        let _ = value;
167    }
168
169    #[inline(always)]
170    fn cache_get<T: 'static>(&mut self) -> Option<T> {
171        None
172    }
173}
174
175/// Byte exhaustion strategy for the driver
176#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
177#[deprecated = "Driver mode should no longer used by generator implementations"]
178pub enum DriverMode {
179    /// When the driver bytes are exhausted, the driver will fail fill input bytes.
180    /// This is useful for fuzz engines that want accurate mapping of inputs to coverage.
181    Direct,
182
183    /// When the driver bytes are exhausted, the driver will continue to fill input bytes with 0.
184    /// This is useful for engines that want to maximize the amount of time spent executing tests.
185    Forced,
186}