use crate::atomic_store;
use crate::error::FeroxFuzzError;
use crate::state::SharedState;
use crate::std_ext::ops::Len;
use crate::Named;
use std::{fmt::Display, sync::atomic::Ordering};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
mod ordered;
mod product;
mod random;
mod unique;
pub use ordered::OrderedScheduler;
pub use product::ProductScheduler;
pub use random::RandomScheduler;
pub use unique::UniqueProductScheduler;
pub trait Scheduler: Named {
fn next(&mut self) -> Result<(), FeroxFuzzError>;
fn reset(&mut self);
fn update_length(&mut self);
}
fn set_states_corpus_index(
state: &SharedState,
corpus_name: &str,
value: usize,
) -> Result<(), FeroxFuzzError> {
let atomic_index = state.corpus_index_by_name(corpus_name)?;
atomic_store!(atomic_index, value);
Ok(())
}
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
struct CorpusIndex {
name: String,
current: usize,
length: usize,
iterations: usize,
}
impl CorpusIndex {
fn new(name: &str, length: usize, iterations: usize) -> Self {
Self {
name: name.to_owned(),
current: 0,
length,
iterations,
}
}
#[inline]
const fn should_reset(&self, total_iterations: usize) -> bool {
total_iterations.is_multiple_of(self.iterations)
}
#[inline]
fn name(&self) -> &str {
&self.name
}
#[inline]
const fn next(&mut self) -> Result<(), FeroxFuzzError> {
if self.current == self.length {
return Err(FeroxFuzzError::IterationStopped);
}
self.current += 1;
Ok(())
}
#[inline]
const fn current(&self) -> usize {
self.current
}
#[inline]
const fn reset(&mut self) {
self.update_current(0);
}
#[inline]
const fn update_length(&mut self, length: usize) {
self.length = length;
}
#[inline]
const fn update_iterations(&mut self, iterations: usize) {
self.iterations = iterations;
}
#[inline]
const fn update_current(&mut self, value: usize) {
self.current = value;
}
}
impl Len for CorpusIndex {
fn len(&self) -> usize {
self.length
}
}
impl Display for CorpusIndex {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}[{}]: {} / {}",
self.name, self.current, self.length, self.iterations
)
}
}