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>;
};
}
pub trait Driver: Sized {
#[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>;
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)>;
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub enum DriverMode {
Direct,
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);
}
}