use alloc::borrow::ToOwned;
use core::marker::PhantomData;
pub mod testcase_score;
pub use testcase_score::{LenTimeMulTestcaseScore, TestcaseScore};
pub mod queue;
pub use queue::QueueScheduler;
pub mod minimizer;
pub use minimizer::{
IndexesLenTimeMinimizerScheduler, LenTimeMinimizerScheduler, MinimizerScheduler,
};
pub mod powersched;
pub use powersched::PowerQueueScheduler;
pub mod probabilistic_sampling;
pub use probabilistic_sampling::ProbabilitySamplingScheduler;
pub mod accounting;
pub use accounting::CoverageAccountingScheduler;
pub mod weighted;
pub use weighted::{StdWeightedScheduler, WeightedScheduler};
pub mod ecofuzz;
pub use ecofuzz::{EcoMetadata, EcoScheduler, EcoState, EcoTestcaseMetadata, EcoTestcaseScore};
pub mod tuneable;
use libafl_bolts::rands::Rand;
pub use tuneable::*;
use crate::{
corpus::{Corpus, CorpusId, HasTestcase, Testcase},
inputs::UsesInput,
observers::ObserversTuple,
random_corpus_id,
state::{HasCorpus, HasRand, State, UsesState},
Error,
};
pub trait RemovableScheduler: Scheduler
where
Self::State: HasCorpus,
{
fn on_remove(
&mut self,
_state: &mut Self::State,
_idx: CorpusId,
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
) -> Result<(), Error> {
Ok(())
}
fn on_replace(
&mut self,
_state: &mut Self::State,
_idx: CorpusId,
_prev: &Testcase<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
Ok(())
}
}
pub trait Scheduler: UsesState
where
Self::State: HasCorpus,
{
fn on_add(&mut self, _state: &mut Self::State, _idx: CorpusId) -> Result<(), Error>;
fn on_evaluation<OT>(
&mut self,
_state: &mut Self::State,
_input: &<Self::State as UsesInput>::Input,
_observers: &OT,
) -> Result<(), Error>
where
OT: ObserversTuple<Self::State>,
{
Ok(())
}
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error>;
fn set_current_scheduled(
&mut self,
state: &mut Self::State,
next_idx: Option<CorpusId>,
) -> Result<(), Error> {
*state.corpus_mut().current_mut() = next_idx;
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct RandScheduler<S> {
phantom: PhantomData<S>,
}
impl<S> UsesState for RandScheduler<S>
where
S: State + HasTestcase,
{
type State = S;
}
impl<S> Scheduler for RandScheduler<S>
where
S: HasCorpus + HasRand + HasTestcase + State,
{
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
let current_idx = *state.corpus().current();
state
.corpus()
.get(idx)?
.borrow_mut()
.set_parent_id_optional(current_idx);
Ok(())
}
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
if state.corpus().count() == 0 {
Err(Error::empty("No entries in corpus".to_owned()))
} else {
let id = random_corpus_id!(state.corpus(), state.rand_mut());
self.set_current_scheduled(state, Some(id))?;
Ok(id)
}
}
}
impl<S> RandScheduler<S> {
#[must_use]
pub fn new() -> Self {
Self {
phantom: PhantomData,
}
}
}
impl<S> Default for RandScheduler<S> {
fn default() -> Self {
Self::new()
}
}
pub type StdScheduler<S> = RandScheduler<S>;