fuzzcheck/mutators/
boxed.rs

1use std::any::Any;
2
3use super::CrossoverStep;
4use crate::{DefaultMutator, Mutator, CROSSOVER_RATE};
5
6/// Default mutator of `Box<T>`
7#[derive(Default)]
8pub struct BoxMutator<M> {
9    mutator: M,
10    rng: fastrand::Rng,
11}
12impl<M> BoxMutator<M> {
13    #[coverage(off)]
14    pub fn new(mutator: M) -> Self {
15        Self {
16            mutator,
17            rng: fastrand::Rng::new(),
18        }
19    }
20}
21#[derive(Clone)]
22pub struct MutationStep<T, MS> {
23    crossover_step: CrossoverStep<T>,
24    inner: MS,
25}
26
27pub enum UnmutateToken<T, U> {
28    Replace(T),
29    Inner(U),
30}
31
32impl<T: Clone + 'static, M: Mutator<T>> Mutator<Box<T>> for BoxMutator<M> {
33    #[doc(hidden)]
34    type Cache = M::Cache;
35    #[doc(hidden)]
36    type MutationStep = MutationStep<T, M::MutationStep>;
37    #[doc(hidden)]
38    type ArbitraryStep = M::ArbitraryStep;
39    #[doc(hidden)]
40    type UnmutateToken = UnmutateToken<T, M::UnmutateToken>;
41
42    #[doc(hidden)]
43    #[coverage(off)]
44    fn initialize(&self) {
45        self.mutator.initialize();
46    }
47
48    #[doc(hidden)]
49    #[coverage(off)]
50    fn default_arbitrary_step(&self) -> Self::ArbitraryStep {
51        self.mutator.default_arbitrary_step()
52    }
53    #[doc(hidden)]
54    #[coverage(off)]
55    fn is_valid(&self, value: &Box<T>) -> bool {
56        self.mutator.is_valid(value)
57    }
58    #[doc(hidden)]
59    #[coverage(off)]
60    fn validate_value(&self, value: &Box<T>) -> Option<Self::Cache> {
61        self.mutator.validate_value(value)
62    }
63    #[doc(hidden)]
64    #[coverage(off)]
65    fn default_mutation_step(&self, value: &Box<T>, cache: &Self::Cache) -> Self::MutationStep {
66        MutationStep {
67            crossover_step: CrossoverStep::default(),
68            inner: self.mutator.default_mutation_step(value, cache),
69        }
70    }
71
72    #[doc(hidden)]
73    #[coverage(off)]
74    fn global_search_space_complexity(&self) -> f64 {
75        self.mutator.global_search_space_complexity()
76    }
77
78    #[doc(hidden)]
79    #[coverage(off)]
80    fn max_complexity(&self) -> f64 {
81        self.mutator.max_complexity()
82    }
83
84    #[doc(hidden)]
85    #[coverage(off)]
86    fn min_complexity(&self) -> f64 {
87        self.mutator.min_complexity()
88    }
89
90    #[doc(hidden)]
91    #[coverage(off)]
92    fn complexity(&self, value: &Box<T>, cache: &Self::Cache) -> f64 {
93        self.mutator.complexity(value, cache)
94    }
95
96    #[doc(hidden)]
97    #[coverage(off)]
98    fn ordered_arbitrary(&self, step: &mut Self::ArbitraryStep, max_cplx: f64) -> Option<(Box<T>, f64)> {
99        if let Some((value, cache)) = self.mutator.ordered_arbitrary(step, max_cplx) {
100            Some((Box::new(value), cache))
101        } else {
102            None
103        }
104    }
105
106    #[doc(hidden)]
107    #[coverage(off)]
108    fn random_arbitrary(&self, max_cplx: f64) -> (Box<T>, f64) {
109        let (value, cache) = self.mutator.random_arbitrary(max_cplx);
110        (Box::new(value), cache)
111    }
112
113    #[doc(hidden)]
114    #[coverage(off)]
115    fn ordered_mutate(
116        &self,
117        value: &mut Box<T>,
118        cache: &mut Self::Cache,
119        step: &mut Self::MutationStep,
120        subvalue_provider: &dyn crate::SubValueProvider,
121        max_cplx: f64,
122    ) -> Option<(Self::UnmutateToken, f64)> {
123        if self.rng.u8(..CROSSOVER_RATE) == 0
124            && let Some((subvalue, subcplx)) = step.crossover_step.get_next_subvalue(subvalue_provider, max_cplx)
125            && self.mutator.is_valid(subvalue)
126        {
127            let mut replacer = subvalue.clone();
128            std::mem::swap(value.as_mut(), &mut replacer);
129            return Some((UnmutateToken::Replace(replacer), subcplx));
130        }
131        if let Some((t, cplx)) = self
132            .mutator
133            .ordered_mutate(value, cache, &mut step.inner, subvalue_provider, max_cplx)
134        {
135            Some((UnmutateToken::Inner(t), cplx))
136        } else {
137            None
138        }
139    }
140
141    #[doc(hidden)]
142    #[coverage(off)]
143    fn random_mutate(&self, value: &mut Box<T>, cache: &mut Self::Cache, max_cplx: f64) -> (Self::UnmutateToken, f64) {
144        let (t, cplx) = self.mutator.random_mutate(value, cache, max_cplx);
145        (UnmutateToken::Inner(t), cplx)
146    }
147
148    #[doc(hidden)]
149    #[coverage(off)]
150    fn unmutate(&self, value: &mut Box<T>, cache: &mut Self::Cache, t: Self::UnmutateToken) {
151        match t {
152            UnmutateToken::Replace(x) => **value = x,
153            UnmutateToken::Inner(t) => self.mutator.unmutate(value, cache, t),
154        }
155    }
156
157    #[doc(hidden)]
158    #[coverage(off)]
159    fn visit_subvalues<'a>(&self, value: &'a Box<T>, cache: &'a Self::Cache, visit: &mut dyn FnMut(&'a dyn Any, f64)) {
160        self.mutator.visit_subvalues(value, cache, visit)
161    }
162}
163
164impl<T> DefaultMutator for Box<T>
165where
166    T: DefaultMutator + 'static,
167{
168    #[doc(hidden)]
169    type Mutator = BoxMutator<<T as DefaultMutator>::Mutator>;
170    #[doc(hidden)]
171    #[coverage(off)]
172    fn default_mutator() -> Self::Mutator {
173        Self::Mutator::new(T::default_mutator())
174    }
175}