use super::*;
use crate::Result;
pub struct Or<M1, M2> {
pub(crate) left: M1,
pub(crate) right: M2,
}
impl<M1, M2, T> Mutate<T> for Or<M1, M2>
where
M1: Mutate<T>,
M2: Mutate<T>,
{
fn mutate(&mut self, c: &mut Candidates, value: &mut T) -> Result<()> {
self.left.mutate(c, value)?;
self.right.mutate(c, value)?;
Ok(())
}
#[inline]
fn mutation_count(&self, value: &T, shrink: bool) -> core::option::Option<u32> {
Some(self.left.mutation_count(value, shrink)? + self.right.mutation_count(value, shrink)?)
}
}
impl<M1, M2, T> Generate<T> for Or<M1, M2>
where
M1: Generate<T>,
M2: Generate<T>,
{
fn generate(&mut self, ctx: &mut Context) -> Result<T> {
if ctx.rng().gen_bool() {
self.left.generate(ctx)
} else {
self.right.generate(ctx)
}
}
}
#[derive(Clone, Debug)]
pub struct Map<M, F> {
pub(crate) mutator: M,
pub(crate) f: F,
}
impl<M, F, T> Mutate<T> for Map<M, F>
where
M: Mutate<T>,
F: FnMut(&mut Context, &mut T) -> Result<()>,
{
fn mutate(&mut self, c: &mut Candidates, value: &mut T) -> Result<()> {
match self.mutator.mutate(c, value) {
Err(e) if e.is_early_exit() => {
(self.f)(&mut c.context, value)?;
Err(Error::early_exit())
}
res => res,
}
}
#[inline]
fn mutation_count(&self, value: &T, shrink: bool) -> core::option::Option<u32> {
self.mutator.mutation_count(value, shrink)
}
}
impl<M, F, T> Generate<T> for Map<M, F>
where
M: Generate<T>,
F: FnMut(&mut Context, &mut T) -> Result<()>,
{
fn generate(&mut self, ctx: &mut Context) -> Result<T> {
let mut value = self.mutator.generate(ctx)?;
(self.f)(ctx, &mut value)?;
Ok(value)
}
}
pub struct Proj<M, F> {
pub(crate) mutator: M,
pub(crate) f: F,
}
impl<M, F, T, U> Mutate<T> for Proj<M, F>
where
M: Mutate<U>,
F: FnMut(&mut T) -> &mut U,
{
#[inline]
fn mutate(&mut self, c: &mut Candidates, value: &mut T) -> Result<()> {
self.mutator.mutate(c, (self.f)(value))
}
}
impl<M, F, T, U> Generate<T> for Proj<M, F>
where
M: Mutate<U>,
F: FnMut(&mut T) -> &mut U,
T: Default,
{
#[inline]
fn generate(&mut self, ctx: &mut Context) -> Result<T> {
self.generate_via_mutate(ctx, 1)
}
}
#[derive(Clone, Debug, Default)]
pub struct Just<T> {
pub(crate) value: T,
}
pub fn just<T>(value: T) -> Just<T> {
Just { value }
}
impl<T> Mutate<T> for Just<T>
where
T: Clone,
{
#[inline]
fn mutate(&mut self, c: &mut Candidates<'_>, value: &mut T) -> Result<()> {
c.mutation(|_| Ok(*value = self.value.clone()))
}
#[inline]
fn mutation_count(&self, _value: &T, _shrink: bool) -> core::option::Option<u32> {
Some(1)
}
}
impl<T> Generate<T> for Just<T>
where
T: Clone,
{
fn generate(&mut self, _ctx: &mut Context) -> Result<T> {
Ok(self.value.clone())
}
}