use crate::test;
use crate::test::Vals;
use crate::BruteforceSearch;
use crate::Callable;
#[derive(Debug, Clone)]
pub struct BruteForce<
Insn,
InputParameters,
ReturnValue: Clone,
TargetFunction: Callable<InputParameters, ReturnValue>,
Searchable: Callable<InputParameters, ReturnValue> + BruteforceSearch<Insn>,
> {
target_function: TargetFunction,
candidate: Searchable,
tests: Vec<(InputParameters, ReturnValue)>,
input: std::marker::PhantomData<InputParameters>,
ret: std::marker::PhantomData<ReturnValue>,
insn: std::marker::PhantomData<Insn>,
pub count: usize,
}
pub trait ToBruteForce<
Insn,
InputParameters,
ReturnValue: Clone,
TargetFunction: Callable<InputParameters, ReturnValue>,
>
{
fn to_bruteforce(
self,
target_function: TargetFunction,
) -> BruteForce<Insn, InputParameters, ReturnValue, TargetFunction, Self>
where
Self: Callable<InputParameters, ReturnValue> + BruteforceSearch<Insn> + Sized;
}
impl<
Insn,
T: Callable<InputParameters, ReturnValue> + BruteforceSearch<Insn> + Clone,
InputParameters,
ReturnValue: Clone + Vals,
TargetFunction: Callable<InputParameters, ReturnValue>,
> ToBruteForce<Insn, InputParameters, ReturnValue, TargetFunction> for T
where
Self: Callable<InputParameters, ReturnValue>,
InputParameters: test::Vals,
{
fn to_bruteforce(
self,
target_function: TargetFunction,
) -> BruteForce<Insn, InputParameters, ReturnValue, TargetFunction, Self> {
BruteForce::new(target_function, self)
}
}
impl<
Insn,
InputParameters: Copy + Vals,
ReturnValue: Vals + std::cmp::PartialEq + Clone,
TargetFunction: Callable<InputParameters, ReturnValue>,
Searchable: Callable<InputParameters, ReturnValue> + crate::BruteforceSearch<Insn> + Clone,
> BruteForce<Insn, InputParameters, ReturnValue, TargetFunction, Searchable>
{
pub fn new(target_function: TargetFunction, initial_candidate: Searchable) -> Self {
let candidate = initial_candidate;
let tests = test::quick_tests(&target_function);
Self {
target_function,
candidate,
tests,
input: std::marker::PhantomData,
insn: std::marker::PhantomData,
ret: std::marker::PhantomData,
count: 0,
}
}
pub fn candidate(&self) -> &Searchable {
&self.candidate
}
pub fn step(&mut self) -> crate::IterationResult {
self.count += 1;
self.candidate.step();
Ok(())
}
pub fn test(&mut self) -> bool {
match test::passes(&self.candidate, &self.tests) {
Err(_) => {
false
}
Ok(false) => {
false
}
Ok(true) => {
if let Some(test_case) = test::fuzz(&self.target_function, &self.candidate, 5000) {
self.tests.push(test_case);
false
} else {
true
}
}
}
}
pub fn search(&mut self) -> Option<Searchable> {
loop {
self.step().ok()?;
if self.test() {
return Some(self.candidate.clone());
}
}
}
}