fuzzcheck_mutators/
enums.rs

1use std::borrow::BorrowMut;
2use std::cmp::Ordering;
3
4use fuzzcheck_traits::Mutator;
5
6pub trait BasicEnumStructure {
7    fn from_item_index(item_index: usize) -> Self;
8    fn get_item_index(&self) -> usize;
9}
10
11#[derive(Default)]
12pub struct BasicEnumMutator {
13    rng: fastrand::Rng,
14}
15
16impl<T> Mutator<T> for BasicEnumMutator
17where
18    T: Clone + BasicEnumStructure,
19{
20    type Cache = ();
21    type MutationStep = usize;
22    type ArbitraryStep = usize;
23    type UnmutateToken = usize;
24
25    fn cache_from_value(&self, _value: &T) -> Self::Cache {}
26
27    fn initial_step_from_value(&self, _value: &T) -> Self::MutationStep {
28        1
29    }
30
31    fn max_complexity(&self) -> f64 {
32        crate::size_to_cplxity(std::mem::variant_count::<T>())
33    }
34
35    fn min_complexity(&self) -> f64 {
36        crate::size_to_cplxity(std::mem::variant_count::<T>())
37    }
38
39    fn complexity(&self, _value: &T, _cache: &Self::Cache) -> f64 {
40        crate::size_to_cplxity(std::mem::variant_count::<T>())
41    }
42
43    fn ordered_arbitrary(&self, step: &mut Self::ArbitraryStep, max_cplx: f64) -> Option<(T, Self::Cache)> {
44        if max_cplx < <Self as Mutator<T>>::min_complexity(self) {
45            return None;
46        }
47        if *step < std::mem::variant_count::<T>() {
48            let old_step = *step;
49            *step += 1;
50            Some((T::from_item_index(old_step), ()))
51        } else {
52            None
53        }
54    }
55
56    fn random_arbitrary(&self, _max_cplx: f64) -> (T, Self::Cache) {
57        let item_idx = self.rng.usize(..std::mem::variant_count::<T>());
58        (T::from_item_index(item_idx), ())
59    }
60
61    fn ordered_mutate(
62        &self,
63        value: &mut T,
64        _cache: &mut Self::Cache,
65        step: &mut Self::MutationStep,
66        max_cplx: f64,
67    ) -> Option<Self::UnmutateToken> {
68        if max_cplx < <Self as Mutator<T>>::min_complexity(self) {
69            return None;
70        }
71        // starts at step = 1
72        // create new from (get_item_index + step) % nbr_of_items
73        if *step < std::mem::variant_count::<T>() {
74            let old_index = value.get_item_index();
75            let old_step = *step;
76            *step += 1;
77            *value = T::from_item_index((old_index + old_step) % std::mem::variant_count::<T>());
78            Some(old_index)
79        } else {
80            None
81        }
82    }
83
84    fn random_mutate(&self, value: &mut T, _cache: &mut Self::Cache, _max_cplx: f64) -> Self::UnmutateToken {
85        let old_index = value.get_item_index();
86        let item_idx = self.rng.usize(..std::mem::variant_count::<T>());
87        *value = T::from_item_index(item_idx);
88        old_index
89    }
90
91    fn unmutate(&self, value: &mut T, _cache: &mut Self::Cache, t: Self::UnmutateToken) {
92        *value = T::from_item_index(t);
93    }
94}
95
96extern crate self as fuzzcheck_mutators;
97
98fuzzcheck_mutators_derive::make_basic_enum_mutators!(1);
99fuzzcheck_mutators_derive::make_basic_enum_mutators!(2);
100fuzzcheck_mutators_derive::make_basic_enum_mutators!(3);
101fuzzcheck_mutators_derive::make_basic_enum_mutators!(4);
102fuzzcheck_mutators_derive::make_basic_enum_mutators!(5);
103fuzzcheck_mutators_derive::make_basic_enum_mutators!(6);
104fuzzcheck_mutators_derive::make_basic_enum_mutators!(7);
105fuzzcheck_mutators_derive::make_basic_enum_mutators!(8);
106fuzzcheck_mutators_derive::make_basic_enum_mutators!(9);
107fuzzcheck_mutators_derive::make_basic_enum_mutators!(10);