Trait mutatis::Mutate

source ·
pub trait Mutate<T>
where T: ?Sized,
{ // Required method fn mutate( &mut self, mutations: &mut Candidates<'_>, value: &mut T, ) -> Result<()>; // Provided methods fn or<M>(self, other: M) -> Or<Self, M> where Self: Sized { ... } fn map<F>(self, f: F) -> Map<Self, F> where Self: Sized, F: FnMut(&mut Context, &mut T) -> Result<()> { ... } fn proj<F, U>(self, f: F) -> Proj<Self, F> where Self: Sized, F: FnMut(&mut U) -> &mut T { ... } fn by_ref(&mut self) -> &mut Self where Self: Sized { ... } }
Expand description

A trait for mutating values.

You can think of Mutate<T> as a streaming iterator of Ts but instead of internally containing and yielding access to the Ts, it takes an &mut T as an argument and mutates it in place.

The main method is the mutate method, which applies one of many potential mutations to the given value, or returns an error.

§Example: Using a Type’s Default Mutator

Many types implement the DefaultMutate trait, which provides a default mutator for that type. You can use this default mutator by calling mutate on a Session with a value of that type.

use mutatis::{Context, Session};

let mut session = Session::new();

let mut x = 1234;
session.mutate(&mut x)?;

for _ in 0..5 {
    session.mutate(&mut x)?;
    println!("mutated x is {x}");
}

panic!();
// Example output:
//
//     mutated x is 1682887620

§Example: Using Custom Mutators

use mutatis::{mutators as m, Mutate, Session};

// Define a mutator for `u32`s that only creates multiples-of-four
let mut mutator = m::u32()
    .map(|_ctx, x| {
        *x = *x & !3; // Clear the bottom two bits to make `x` a multiple of four.
        Ok(())
    });

// Mutate a value a bunch of times!
let mut x = 1234;
let mut session = Session::new();
for _ in 0..5 {
    session.mutate_with(&mut mutator, &mut x)?;
    println!("mutated x is {x}");
}

panic!();
// Example output:
//
//     mutated x is 2436583184
//     mutated x is 2032949584
//     mutated x is 2631247496
//     mutated x is 199875380
//     mutated x is 3751781284

§Exhaustion

A mutator may become exhausted, meaning that it doesn’t have any more mutations it can perform for a given value. In this case, the mutator may return an error of kind ErrorKind::Exhausted. Many mutators are effectively inexhaustible (or it would be prohibitively expensive to precisely track whether they’ve already emitted every possible variant of a value) and therefore it is valid for a mutator to never report exhaustion.

You may also ignore exhaustion errors via the mutatis::error::ResultExt::ignore_exhausted extension method.

Note that you should never return an ErrorKind::Exhausted error from your own manual Mutate implementations. Instead, simply avoid registering any candidate mutations and, if no other sibling or parent mutators have any potential mutations either, then the library will return an exhaustion error for you.

§Many-to-Many

Note that the relationship between mutator types and mutated types is not one-to-one: a single mutator type can mutate many different types, and a single type can be mutated by many different mutator types. This gives you the flexibility to define new mutators for existing types (including those that are not defined by your own crate).

use mutatis::{
    mutators as m, DefaultMutate, Mutate, Session, Candidates,
    Result,
};

#[derive(Mutate)] // Derive a default mutator for `Foo`s.
pub struct Foo(u32);

// Also define and implement a second mutator type for `Foo` by hand!

pub struct AlignedFooMutator{
    inner: <Foo as DefaultMutate>::DefaultMutate,
    alignment: u32,
}

impl Mutate<Foo> for AlignedFooMutator {
    fn mutate(&mut self, mutations: &mut Candidates, foo: &mut Foo) -> Result<()> {
        self.inner
            .by_ref()
            .map(|_context, foo| {
                // Clear the bottom bits to keep the `Foo` "aligned".
                debug_assert!(self.alignment.is_power_of_two());
                let mask = !(self.alignment - 1);
                foo.0 = foo.0 & mask;
                Ok(())
            })
            .mutate(mutations, foo)
    }
}

Required Methods§

source

fn mutate( &mut self, mutations: &mut Candidates<'_>, value: &mut T, ) -> Result<()>

Pseudo-randomly mutate the given value.

§Calling the mutate Method

If you just want to mutate a value, use Session::mutate or Session::mutate_with instead of invoking this trait method directly. See their documentation for more details.

§Implementing the mutate Method

Register every mutation that a mutator could perform by invoking the mutations.mutation(...) function, passing in a closure that performs that mutation, updating value and self as necessary.

mutate implementations must only mutate self and the given value from inside a registered mutation closure. It must not update self or modify value outside of one of those mutation closures.

Furthermore, all mutate implementations must be deterministic: given the same inputs, the same set of mutations must be registered in the same order.

These requirements exist because, under the hood, the mutate method is called twice for every mutation that is actually performed:

  1. First, mutate is called to count all the possible mutations that could be performed. In this phase, the mutation closures are ignored.

  2. Next, a random index i between 0 and that count is chosen. This is the index of the mutation that we will actually be applied.

  3. Finally, mutate is called again. In this phase, the ith mutation closure is invoked, applying the mutation, while all others are ignored.

Note that the registered mutations are roughly uniformly selected from, so if you wish to skew the distribution of mutations, making certain mutations more probable than others, you may register mutations multiple times or register overlapping mutations.

§Example
use mutatis::{
    mutators as m, Generate, Mutate, Session, Candidates,
    Result,
};

// A custom mutator that creates pairs where the first element is less
// than or equal to the second.
pub struct OrderedPairs;

impl Mutate<(u64, u64)> for OrderedPairs {
    fn mutate(
        &mut self,
        mutations: &mut Candidates<'_>,
        pair: &mut (u64, u64),
    ) -> Result<()> {
        // We *cannot* mutate `self` or `pair` out here.

        if *pair != (0, 0) {
            // Note: we register this mutation -- even when not
            // shrinking and even though the subsequent mutation
            // subsumes this one -- to bias the distribution towards
            // smaller values.
            mutations.mutation(|ctx| {
                // We *can* mutate `self` and `pair` inside here.
                let a = m::range(0..=pair.0).generate(ctx)?;
                let b = m::range(0..=pair.1).generate(ctx)?;
                *pair = (a.min(b), a.max(b));
                Ok(())
            })?;
        }

        if !mutations.shrink() {
            // Only register this fully-general mutation when we are
            // not shrinking, as this can grow the pair.
            mutations.mutation(|ctx| {
                // We *can* mutate `self` and `pair` inside here.
                let a = m::u64().generate(ctx)?;
                let b = m::u64().generate(ctx)?;
                *pair = (a.min(b), a.max(b));
                Ok(())
            })?;
        }

        Ok(())
    }
}

// Create a pair.
let mut pair = (1000, 2000);

// And mutate it a bunch of times!
let mut session = Session::new();
for _ in 0..3 {
    session.mutate_with(&mut OrderedPairs, &mut pair)?;
    println!("mutated pair is {pair:?}");
}

// Example output:
//
//     mutated pair is (11, 861)
//     mutated pair is (8, 818)
//     mutated pair is (3305948426120559093, 16569598107406464568)

Provided Methods§

source

fn or<M>(self, other: M) -> Or<Self, M>
where Self: Sized,

Create a new mutator that performs either this mutation or the other mutation.

§Example
use mutatis::{mutators as m, Mutate, Session};

let mut session = Session::new();

// Either generate `-1`...
let mut mutator = m::just(-1)
    // ...or values in the range `0x40..=0x4f`...
    .or(m::range(0x40..=0x4f))
    // ...or values with just a single bit set.
    .or(m::range(0..=31).map(|_ctx, x| {
        *x = 1 << *x;
        Ok(())
    }));

let mut value = 0;

for _ in 0..5 {
    session.mutate_with(&mut mutator, &mut value)?;
    println!("mutated value is {value:#x}");
}

// Example output:
//
//     mutated value is 0x4a
//     mutated value is 0xffffffff
//     mutated value is 0x400000
//     mutated value is 0x20000000
//     mutated value is 0x4e
source

fn map<F>(self, f: F) -> Map<Self, F>
where Self: Sized, F: FnMut(&mut Context, &mut T) -> Result<()>,

Map a function over the mutations produced by this mutator.

§Example
use mutatis::{mutators as m, Mutate, Session};

let mut session = Session::new();

let mut mutator = m::i32().map(|context, value| {
    // Ensure that the value is always positive.
    if *value <= 0 {
        *value = i32::from(context.rng().gen_u16());
    }
    Ok(())
});

let mut value = -42;

for _ in 0..10 {
    session.mutate_with(&mut mutator, &mut value)?;
    assert!(value > 0, "the mutated value is always positive");
}
source

fn proj<F, U>(self, f: F) -> Proj<Self, F>
where Self: Sized, F: FnMut(&mut U) -> &mut T,

Given a projection function F: FnMut(&mut U) -> &mut T, turn this Mutate<T> into a Mutate<U>.

§Example
use mutatis::{mutators as m, Mutate, Session};

#[derive(Debug)]
pub struct NewType(u32);

let mut value = NewType(0);

let mut mutator = m::u32().proj(|x: &mut NewType| &mut x.0);

let mut session = Session::new();
for _ in 0..3 {
   session.mutate_with(&mut mutator, &mut value)?;
   println!("mutated value is {value:?}");
}

// Example output:
//
//     mutated value is NewType(3729462868)
//     mutated value is NewType(49968845)
//     mutated value is NewType(2440803355)
source

fn by_ref(&mut self) -> &mut Self
where Self: Sized,

Borrows a mutator, rather than consuming it.

This is useful to allow applying mutator adapters while still retaining ownership of the original mutator.

§Example
use mutatis::{mutators as m, Mutate, Session};

let mut mutator = m::u32().map(|_context, x| {
    *x = *x & !3;
    Ok(())
});


let mut value = 1234;
let mut session = Session::new();

{
    let mut borrowed_mutator = mutator.by_ref().map(|_context, x| {
        *x = x.wrapping_add(1);
        Ok(())
    });
    session.mutate_with(&mut borrowed_mutator, &mut value)?;
    println!("first mutated value is {value}");
}

// In the outer scope, we can still use the original mutator.
session.mutate_with(&mut mutator, &mut value)?;
println!("second mutated value is {value}");

// Example output:
//
//     first mutated value is 3729462869
//     second mutated value is 49968844

Implementations on Foreign Types§

source§

impl<M, T> Mutate<T> for &mut M
where M: Mutate<T>,

source§

fn mutate(&mut self, c: &mut Candidates<'_>, value: &mut T) -> Result<()>

Implementors§

source§

impl Mutate<bool> for Bool

source§

impl Mutate<char> for Char

source§

impl Mutate<f32> for F32

source§

impl Mutate<f64> for F64

source§

impl Mutate<i8> for I8

source§

impl Mutate<i16> for I16

source§

impl Mutate<i32> for I32

source§

impl Mutate<i64> for I64

source§

impl Mutate<i128> for I128

source§

impl Mutate<isize> for Isize

source§

impl Mutate<u8> for U8

source§

impl Mutate<u16> for U16

source§

impl Mutate<u32> for U32

source§

impl Mutate<u64> for U64

source§

impl Mutate<u128> for U128

source§

impl Mutate<()> for Unit

source§

impl Mutate<usize> for Usize

source§

impl<M0, T0> Mutate<(T0,)> for Tuple1<M0>
where M0: Mutate<T0>,

source§

impl<M0, T0, M1, T1> Mutate<(T0, T1)> for Tuple2<M0, M1>
where M0: Mutate<T0>, M1: Mutate<T1>,

source§

impl<M0, T0, M1, T1, M2, T2> Mutate<(T0, T1, T2)> for Tuple3<M0, M1, M2>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3> Mutate<(T0, T1, T2, T3)> for Tuple4<M0, M1, M2, M3>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4> Mutate<(T0, T1, T2, T3, T4)> for Tuple5<M0, M1, M2, M3, M4>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5> Mutate<(T0, T1, T2, T3, T4, T5)> for Tuple6<M0, M1, M2, M3, M4, M5>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6> Mutate<(T0, T1, T2, T3, T4, T5, T6)> for Tuple7<M0, M1, M2, M3, M4, M5, M6>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7)> for Tuple8<M0, M1, M2, M3, M4, M5, M6, M7>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>, M7: Mutate<T7>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8)> for Tuple9<M0, M1, M2, M3, M4, M5, M6, M7, M8>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>, M7: Mutate<T7>, M8: Mutate<T8>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)> for Tuple10<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>, M7: Mutate<T7>, M8: Mutate<T8>, M9: Mutate<T9>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> for Tuple11<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>, M7: Mutate<T7>, M8: Mutate<T8>, M9: Mutate<T9>, M10: Mutate<T10>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)> for Tuple12<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>, M7: Mutate<T7>, M8: Mutate<T8>, M9: Mutate<T9>, M10: Mutate<T10>, M11: Mutate<T11>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11, M12, T12> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)> for Tuple13<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>, M7: Mutate<T7>, M8: Mutate<T8>, M9: Mutate<T9>, M10: Mutate<T10>, M11: Mutate<T11>, M12: Mutate<T12>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11, M12, T12, M13, T13> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)> for Tuple14<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>, M7: Mutate<T7>, M8: Mutate<T8>, M9: Mutate<T9>, M10: Mutate<T10>, M11: Mutate<T11>, M12: Mutate<T12>, M13: Mutate<T13>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11, M12, T12, M13, T13, M14, T14> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)> for Tuple15<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>, M7: Mutate<T7>, M8: Mutate<T8>, M9: Mutate<T9>, M10: Mutate<T10>, M11: Mutate<T11>, M12: Mutate<T12>, M13: Mutate<T13>, M14: Mutate<T14>,

source§

impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11, M12, T12, M13, T13, M14, T14, M15, T15> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)> for Tuple16<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15>
where M0: Mutate<T0>, M1: Mutate<T1>, M2: Mutate<T2>, M3: Mutate<T3>, M4: Mutate<T4>, M5: Mutate<T5>, M6: Mutate<T6>, M7: Mutate<T7>, M8: Mutate<T8>, M9: Mutate<T9>, M10: Mutate<T10>, M11: Mutate<T11>, M12: Mutate<T12>, M13: Mutate<T13>, M14: Mutate<T14>, M15: Mutate<T15>,

source§

impl<M1, M2, T> Mutate<T> for Or<M1, M2>
where M1: Mutate<T>, M2: Mutate<T>,

source§

impl<M, F, T> Mutate<T> for Map<M, F>
where M: Mutate<T>, F: FnMut(&mut Context, &mut T) -> Result<()>,

source§

impl<M, F, T, U> Mutate<T> for Proj<M, F>
where M: Mutate<U>, F: FnMut(&mut T) -> &mut U,

source§

impl<M, T> Mutate<Option<T>> for Option<M>
where M: Generate<T>,

source§

impl<M, T> Mutate<Option<T>> for Some<M>
where M: Generate<T>,

source§

impl<M, T> Mutate<T> for Range<M, T>
where M: MutateInRange<T>,

source§

impl<T> Mutate<Option<T>> for None

source§

impl<T> Mutate<T> for Just<T>
where T: Clone,

source§

impl<const N: usize, M, T> Mutate<[T; N]> for Array<N, M>
where M: Mutate<T>,