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
use crate::{
uniform::{FillBytes, Uniform},
TypeGenerator,
};
use core::ops::{Bound, RangeInclusive};
use rand_core::RngCore;
#[macro_use]
mod macros;
mod bytes;
mod rng;
pub use bytes::ByteSliceDriver;
pub use rng::{DirectRng, ForcedRng};
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`
fn gen<T: TypeGenerator>(&mut self) -> Option<T> {
T::generate(self)
}
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<Gen, T>(&mut self, len: RangeInclusive<usize>, gen: Gen) -> Option<T>
where
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,
}