use crate::{
uniform::{FillBytes, Uniform},
TypeGenerator, ValueGenerator,
};
use core::ops::Bound;
use rand_core::TryRngCore;
#[macro_use]
mod macros;
pub mod bytes;
#[cfg(feature = "alloc")]
pub mod cache;
#[cfg(feature = "alloc")]
pub mod exhaustive;
pub mod object;
mod options;
mod rng;
pub use bytes::ByteSliceDriver;
pub use options::Options;
pub use rng::Rng;
macro_rules! gen_method {
($name:ident, $constant:ident, $ty:ty) => {
fn $name(&mut self, min: Bound<&$ty>, max: Bound<&$ty>) -> Option<$ty>;
#[inline(always)]
fn $constant(&mut self, value: $ty) -> Option<$ty> {
Some(value)
}
};
}
pub trait Driver: Sized {
#[inline(always)]
fn produce<T: TypeGenerator>(&mut self) -> Option<T> {
T::generate(self)
}
#[deprecated = "Use `produce` instead (`gen` conflicts with edition2024)"]
#[inline(always)]
fn gen<T: TypeGenerator>(&mut self) -> Option<T> {
self.produce()
}
#[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;
#[inline(always)]
fn enter_product<Output, F, Ret>(&mut self, mut f: F) -> Option<Ret>
where
Output: 'static,
F: FnMut(&mut Self) -> Option<Ret>,
{
f(self)
}
#[inline(always)]
fn enter_sum<Output, F, Ret>(
&mut self,
element_names: Option<&'static [&'static str]>,
elements: usize,
base_case: usize,
mut f: F,
) -> Option<Ret>
where
Output: 'static,
F: FnMut(&mut Self, usize) -> Option<Ret>,
{
let _ = element_names;
let idx = self.gen_variant(elements, base_case)?;
f(self, idx)
}
#[inline(always)]
fn enter_list<Output, F, Len, Ret>(&mut self, lens: &Len, mut f: F) -> Option<Ret>
where
Output: 'static,
F: FnMut(&mut Self, usize) -> Option<Ret>,
Len: ValueGenerator<Output = usize>,
{
self.depth_guard(|driver| {
let len = lens.generate(driver)?;
f(driver, len)
})
}
#[inline(always)]
fn enter_combinator<Output, F, Ret>(&mut self, mut f: F) -> Option<Ret>
where
Output: 'static,
F: FnMut(&mut Self) -> Option<Ret>,
{
f(self)
}
fn gen_variant(&mut self, variants: usize, base_case: usize) -> Option<usize>;
gen_method!(gen_u8, gen_u8_constant, u8);
gen_method!(gen_i8, gen_i8_constant, i8);
gen_method!(gen_u16, gen_u16_constant, u16);
gen_method!(gen_i16, gen_i16_constant, i16);
gen_method!(gen_u32, gen_u32_constant, u32);
gen_method!(gen_i32, gen_i32_constant, i32);
gen_method!(gen_u64, gen_u64_constant, u64);
gen_method!(gen_i64, gen_i64_constant, i64);
gen_method!(gen_u128, gen_u128_constant, u128);
gen_method!(gen_i128, gen_i128_constant, i128);
gen_method!(gen_usize, gen_usize_constant, usize);
gen_method!(gen_isize, gen_isize_constant, isize);
gen_method!(gen_f32, gen_f32_constant, f32);
gen_method!(gen_f64, gen_f64_constant, f64);
gen_method!(gen_char, gen_char_constant, char);
fn gen_bool(&mut self, probability: Option<f32>) -> Option<bool>;
fn gen_from_bytes<Hint, Gen, T>(&mut self, hint: Hint, produce: Gen) -> Option<T>
where
Hint: FnOnce() -> (usize, Option<usize>),
Gen: FnMut(&[u8]) -> Option<(usize, T)>;
#[inline(always)]
fn cache_put<T: 'static>(&mut self, value: T) {
let _ = value;
}
#[inline(always)]
fn cache_get<T: 'static>(&mut self) -> Option<T> {
None
}
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
#[deprecated = "Driver mode should no longer used by generator implementations"]
pub enum DriverMode {
Direct,
Forced,
}