pub mod testcase;
pub use testcase::{PowerScheduleTestcaseMetaData, Testcase};
pub mod inmemory;
pub use inmemory::InMemoryCorpus;
#[cfg(feature = "std")]
pub mod ondisk;
#[cfg(feature = "std")]
pub use ondisk::OnDiskCorpus;
#[cfg(feature = "std")]
pub mod cached;
#[cfg(feature = "std")]
pub use cached::CachedOnDiskCorpus;
pub mod queue;
pub use queue::QueueCorpusScheduler;
pub mod minimizer;
pub use minimizer::{
FavFactor, IndexesLenTimeMinimizerCorpusScheduler, IsFavoredMetadata,
LenTimeMinimizerCorpusScheduler, LenTimeMulFavFactor, MinimizerCorpusScheduler,
TopRatedsMetadata,
};
pub mod powersched;
pub use powersched::PowerQueueCorpusScheduler;
use alloc::borrow::ToOwned;
use core::{cell::RefCell, marker::PhantomData};
use crate::{
bolts::rands::Rand,
inputs::Input,
state::{HasCorpus, HasRand},
Error,
};
pub trait Corpus<I>: serde::Serialize + serde::de::DeserializeOwned
where
I: Input,
{
fn count(&self) -> usize;
fn is_empty(&self) -> bool {
self.count() == 0
}
fn add(&mut self, testcase: Testcase<I>) -> Result<usize, Error>;
fn replace(&mut self, idx: usize, testcase: Testcase<I>) -> Result<(), Error>;
fn remove(&mut self, idx: usize) -> Result<Option<Testcase<I>>, Error>;
fn get(&self, idx: usize) -> Result<&RefCell<Testcase<I>>, Error>;
fn current(&self) -> &Option<usize>;
fn current_mut(&mut self) -> &mut Option<usize>;
}
pub trait CorpusScheduler<I, S>
where
I: Input,
{
fn on_add(&self, _state: &mut S, _idx: usize) -> Result<(), Error> {
Ok(())
}
fn on_replace(
&self,
_state: &mut S,
_idx: usize,
_testcase: &Testcase<I>,
) -> Result<(), Error> {
Ok(())
}
fn on_remove(
&self,
_state: &mut S,
_idx: usize,
_testcase: &Option<Testcase<I>>,
) -> Result<(), Error> {
Ok(())
}
fn next(&self, state: &mut S) -> Result<usize, Error>;
}
pub struct RandCorpusScheduler<C, I, R, S>
where
S: HasCorpus<C, I> + HasRand<R>,
C: Corpus<I>,
I: Input,
R: Rand,
{
phantom: PhantomData<(C, I, R, S)>,
}
impl<C, I, R, S> CorpusScheduler<I, S> for RandCorpusScheduler<C, I, R, S>
where
S: HasCorpus<C, I> + HasRand<R>,
C: Corpus<I>,
I: Input,
R: Rand,
{
fn next(&self, state: &mut S) -> Result<usize, Error> {
if state.corpus().count() == 0 {
Err(Error::Empty("No entries in corpus".to_owned()))
} else {
let len = state.corpus().count();
let id = state.rand_mut().below(len as u64) as usize;
*state.corpus_mut().current_mut() = Some(id);
Ok(id)
}
}
}
impl<C, I, R, S> RandCorpusScheduler<C, I, R, S>
where
S: HasCorpus<C, I> + HasRand<R>,
C: Corpus<I>,
I: Input,
R: Rand,
{
#[must_use]
pub fn new() -> Self {
Self {
phantom: PhantomData,
}
}
}
impl<C, I, R, S> Default for RandCorpusScheduler<C, I, R, S>
where
S: HasCorpus<C, I> + HasRand<R>,
C: Corpus<I>,
I: Input,
R: Rand,
{
fn default() -> Self {
Self::new()
}
}
pub type StdCorpusScheduler<C, I, R, S> = RandCorpusScheduler<C, I, R, S>;