1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
use crate::{
    uniform::{FillBytes, Uniform},
    TypeGenerator,
};
use core::ops::Bound;
use rand_core::RngCore;

#[macro_use]
mod macros;

mod bytes;
mod rng;

pub use bytes::ByteSliceDriver;
pub use rng::Rng;

macro_rules! gen_method {
    ($name:ident, $ty:ty) => {
        fn $name(&mut self, min: Bound<&$ty>, max: Bound<&$ty>) -> Option<$ty>;
    };
}

/// Trait for driving the generation of a value
///
/// In a test engine, this is typically backed by
/// a byte slice, but other drivers can be used instead, e.g.
/// an RNG implementation.
pub trait Driver: Sized {
    /// Generate a value with type `T`
    #[inline]
    fn gen<T: TypeGenerator>(&mut self) -> Option<T> {
        T::generate(self)
    }

    #[inline]
    fn depth_guard<F, R>(&mut self, f: F) -> Option<R>
    where
        F: FnOnce(&mut Self) -> Option<R>,
    {
        let depth = self.depth();
        if depth == self.max_depth() {
            return None;
        }

        let new_depth = depth + 1;
        self.set_depth(new_depth);
        let value = f(self);
        self.set_depth(depth);

        value
    }

    fn depth(&self) -> usize;

    fn set_depth(&mut self, depth: usize);

    fn max_depth(&self) -> usize;

    fn gen_variant<T: TypeGenerator + Uniform>(&mut self, variants: T, base_case: T) -> Option<T>;

    gen_method!(gen_u8, u8);
    gen_method!(gen_i8, i8);
    gen_method!(gen_u16, u16);
    gen_method!(gen_i16, i16);
    gen_method!(gen_u32, u32);
    gen_method!(gen_i32, i32);
    gen_method!(gen_u64, u64);
    gen_method!(gen_i64, i64);
    gen_method!(gen_u128, u128);
    gen_method!(gen_i128, i128);
    gen_method!(gen_usize, usize);
    gen_method!(gen_isize, isize);
    gen_method!(gen_f32, f32);
    gen_method!(gen_f64, f64);
    gen_method!(gen_char, char);

    fn gen_bool(&mut self, probability: Option<f32>) -> Option<bool>;

    /// Generate a value from bytes off this generator
    ///
    /// `len` is the size of the slice that should be passed to `gen`. The range's minimal size
    /// is the minimal amount of bytes needed to properly generate an input. The range's maximal
    /// value should be so that every `T` can be generated by `gen` from a slice of this length.
    ///
    /// `gen` is the function that actually does the generation. It takes as input the byte slice,
    /// and returns either `None` (if not enough bytes were provided to build a `T`, this can
    /// happen even with a slice of maximum length but should happen as rarely as possible), or
    /// a `Some` value if it could generate a `T`. In this case, it also returns the number of
    /// bytes that were actually consumed from the slice.
    ///
    /// Note that `gen` may be called multiple times with increasing slice lengths, eg. if the
    /// driver is in forced mode.
    fn gen_from_bytes<Hint, Gen, T>(&mut self, hint: Hint, gen: Gen) -> Option<T>
    where
        Hint: FnOnce() -> (usize, Option<usize>),
        Gen: FnMut(&[u8]) -> Option<(usize, T)>;
}

/// Byte exhaustion strategy for the driver
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub enum DriverMode {
    /// When the driver bytes are exhausted, the driver will fail fill input bytes.
    /// This is useful for fuzz engines that want accurate mapping of inputs to coverage.
    Direct,

    /// When the driver bytes are exhausted, the driver will continue to fill input bytes with 0.
    /// This is useful for engines that want to maximize the amount of time spent executing tests.
    Forced,
}

#[derive(Clone, Debug, Default)]
pub struct Options {
    driver_mode: Option<DriverMode>,
    shrink_time: Option<core::time::Duration>,
    max_depth: Option<usize>,
}

impl Options {
    pub const DEFAULT_MAX_DEPTH: usize = 32;
    pub const DEFAULT_SHRINK_TIME: core::time::Duration = core::time::Duration::from_secs(1);

    pub fn with_driver_mode(mut self, driver_mode: DriverMode) -> Self {
        self.driver_mode = Some(driver_mode);
        self
    }

    pub fn with_shrink_time(mut self, shrink_time: core::time::Duration) -> Self {
        self.shrink_time = Some(shrink_time);
        self
    }

    pub fn with_max_depth(mut self, max_depth: usize) -> Self {
        self.max_depth = Some(max_depth);
        self
    }

    pub fn set_driver_mode(&mut self, driver_mode: DriverMode) -> &mut Self {
        self.driver_mode = Some(driver_mode);
        self
    }

    pub fn set_shrink_time(&mut self, shrink_time: core::time::Duration) -> &mut Self {
        self.shrink_time = Some(shrink_time);
        self
    }

    pub fn set_max_depth(&mut self, max_depth: usize) -> &mut Self {
        self.max_depth = Some(max_depth);
        self
    }

    #[inline]
    pub fn max_depth(&self) -> Option<usize> {
        self.max_depth
    }

    #[inline]
    pub fn shrink_time(&self) -> Option<core::time::Duration> {
        self.shrink_time
    }

    #[inline]
    pub fn driver_mode(&self) -> Option<DriverMode> {
        self.driver_mode
    }

    #[inline]
    pub fn max_depth_or_default(&self) -> usize {
        self.max_depth.unwrap_or(Self::DEFAULT_MAX_DEPTH)
    }

    #[inline]
    pub fn shrink_time_or_default(&self) -> core::time::Duration {
        self.shrink_time.unwrap_or(Self::DEFAULT_SHRINK_TIME)
    }

    #[inline]
    pub fn merge_from(&mut self, other: &Self) {
        macro_rules! merge {
            ($name:ident) => {
                if let Some($name) = other.$name {
                    self.$name = Some($name);
                }
            };
        }

        merge!(driver_mode);
        merge!(max_depth);
        merge!(shrink_time);
    }
}