fuzzcheck/mutators/
boxed.rs1use std::any::Any;
2
3use super::CrossoverStep;
4use crate::{DefaultMutator, Mutator, CROSSOVER_RATE};
5
6#[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}