use super::*;
use ::core::{marker::PhantomData, ops};
use rand::Rng;
mod combinators;
mod core_impls;
pub use combinators::*;
pub use core_impls::*;
#[cfg(feature = "alloc")]
mod alloc_impls;
#[cfg(feature = "alloc")]
pub use alloc_impls::*;
#[cfg(feature = "std")]
mod std_impls;
#[cfg(feature = "std")]
pub use std_impls::*;
#[derive(Clone, Debug)]
pub struct Nop<T> {
_phantom: PhantomData<fn(&mut T)>,
}
pub fn nop<T>() -> Nop<T> {
Nop {
_phantom: PhantomData,
}
}
impl<T> Mutate<T> for Nop<T> {
fn mutate(&mut self, c: &mut Candidates<'_>, _value: &mut T) -> Result<()> {
c.mutation(|_| Ok(()))
}
}
impl<T: Default> Generate<T> for Nop<T> {
fn generate(&mut self, _ctx: &mut Context) -> Result<T> {
Ok(T::default())
}
}
pub struct FromFn<F, T> {
func: F,
_phantom: PhantomData<fn(&mut T)>,
}
pub fn from_fn<F, T>(func: F) -> FromFn<F, T> {
FromFn {
func,
_phantom: PhantomData,
}
}
impl<F, T> Mutate<T> for FromFn<F, T>
where
F: FnMut(&mut Context, &mut T) -> Result<()>,
{
fn mutate(&mut self, c: &mut Candidates<'_>, value: &mut T) -> Result<()> {
c.mutation(|ctx| (self.func)(ctx, value))
}
}
impl<F, T: Default> Generate<T> for FromFn<F, T>
where
F: FnMut(&mut Context, &mut T) -> Result<()>,
{
fn generate(&mut self, ctx: &mut Context) -> Result<T> {
self.generate_via_mutate(ctx, 1)
}
}
pub fn default<T>() -> <T as DefaultMutate>::DefaultMutate
where
T: DefaultMutate,
{
T::DefaultMutate::default()
}
#[derive(Clone, Debug)]
pub struct MRange<M, T> {
mutator: M,
range: ops::RangeInclusive<T>,
}
pub fn mrange<T>(range: ops::RangeInclusive<T>) -> MRange<T::DefaultMutate, T>
where
T: DefaultMutate,
{
let mutator = default::<T>();
MRange { mutator, range }
}
pub fn range_with<M, T>(range: ops::RangeInclusive<T>, mutator: M) -> MRange<M, T> {
MRange { mutator, range }
}
impl<M, T> Mutate<T> for MRange<M, T>
where
M: MutateInRange<T>,
{
#[inline]
fn mutate(&mut self, c: &mut Candidates, value: &mut T) -> crate::Result<()> {
self.mutator.mutate_in_range(c, value, &self.range)
}
}
impl<M, T> Generate<T> for MRange<M, T>
where
M: Generate<T> + MutateInRange<T>,
{
#[inline]
fn generate(&mut self, context: &mut Context) -> crate::Result<T> {
let mut value = self.mutator.generate(context)?;
context.mutate_in_range_with(&mut self.mutator, &mut value, &self.range)?;
Ok(value)
}
}