1use crate::test;
2use crate::test::Vals;
3use crate::BruteforceSearch;
4use crate::Callable;
5
6#[derive(Debug, Clone)]
8pub struct BruteForce<
9 Insn,
10 InputParameters,
11 ReturnValue: Clone,
12 TargetFunction: Callable<InputParameters, ReturnValue>,
13 Searchable: Callable<InputParameters, ReturnValue> + BruteforceSearch<Insn>,
14> {
15 target_function: TargetFunction,
16 candidate: Searchable,
17 tests: Vec<(InputParameters, ReturnValue)>,
18 input: std::marker::PhantomData<InputParameters>,
19 ret: std::marker::PhantomData<ReturnValue>,
20 insn: std::marker::PhantomData<Insn>,
21
22 pub count: usize,
24}
25
26pub trait ToBruteForce<
29 Insn,
30 InputParameters,
31 ReturnValue: Clone,
32 TargetFunction: Callable<InputParameters, ReturnValue>,
33>
34{
35 fn to_bruteforce(
37 self,
38 target_function: TargetFunction,
39 ) -> BruteForce<Insn, InputParameters, ReturnValue, TargetFunction, Self>
40 where
41 Self: Callable<InputParameters, ReturnValue> + BruteforceSearch<Insn> + Sized;
42}
43
44impl<
45 Insn,
46 T: Callable<InputParameters, ReturnValue> + BruteforceSearch<Insn> + Clone,
47 InputParameters,
48 ReturnValue: Clone + Vals,
49 TargetFunction: Callable<InputParameters, ReturnValue>,
50 > ToBruteForce<Insn, InputParameters, ReturnValue, TargetFunction> for T
51where
52 Self: Callable<InputParameters, ReturnValue>,
53 InputParameters: test::Vals,
54{
55 fn to_bruteforce(
56 self,
57 target_function: TargetFunction,
58 ) -> BruteForce<Insn, InputParameters, ReturnValue, TargetFunction, Self> {
59 BruteForce::new(target_function, self)
60 }
61}
62
63impl<
64 Insn,
65 InputParameters: Copy + Vals,
66 ReturnValue: Vals + std::cmp::PartialEq + Clone,
67 TargetFunction: Callable<InputParameters, ReturnValue>,
68 Searchable: Callable<InputParameters, ReturnValue> + crate::BruteforceSearch<Insn> + Clone,
69 > BruteForce<Insn, InputParameters, ReturnValue, TargetFunction, Searchable>
70{
71 pub fn new(target_function: TargetFunction, initial_candidate: Searchable) -> Self {
73 let candidate = initial_candidate;
74 let tests = test::quick_tests(&target_function);
75 Self {
76 target_function,
77 candidate,
78 tests,
79 input: std::marker::PhantomData,
80 insn: std::marker::PhantomData,
81 ret: std::marker::PhantomData,
82 count: 0,
83 }
84 }
85
86 pub fn candidate(&self) -> &Searchable {
88 &self.candidate
89 }
90
91 pub fn step(&mut self) -> crate::IterationResult {
93 self.count += 1;
94 self.candidate.step();
95 Ok(())
96 }
97
98 pub fn test(&mut self) -> bool {
100 match test::passes(&self.candidate, &self.tests) {
101 Err(_) => {
102 false
104 }
105 Ok(false) => {
106 false
108 }
109 Ok(true) => {
110 if let Some(test_case) = test::fuzz(&self.target_function, &self.candidate, 5000) {
113 self.tests.push(test_case);
116 false
117 } else {
118 true
121 }
122 }
123 }
124 }
125
126 pub fn search(&mut self) -> Option<Searchable> {
128 loop {
129 self.step().ok()?;
130 if self.test() {
131 return Some(self.candidate.clone());
132 }
133 }
134 }
135}