use alloc::vec::Vec;
use core::{marker::PhantomData, num::NonZeroUsize};
use libafl_bolts::rands::Rand;
use crate::{Error, inputs::bytes::BytesInput, nonzero, state::HasRand};
pub mod gramatron;
use core::cmp::max;
pub use gramatron::*;
#[cfg(feature = "nautilus")]
pub mod nautilus;
#[cfg(feature = "nautilus")]
pub use nautilus::*;
pub trait Generator<I, S> {
fn generate(&mut self, state: &mut S) -> Result<I, Error>;
}
impl<T, I, S> Generator<I, S> for T
where
T: Iterator<Item = I>,
{
fn generate(&mut self, _state: &mut S) -> Result<I, Error> {
match self.next() {
Some(i) => Ok(i),
None => Err(Error::empty(
"No more items in iterator when generating inputs",
)),
}
}
}
#[derive(Debug)]
pub struct GeneratorIter<'a, I, S, G> {
generator: G,
state: &'a mut S,
phantom: PhantomData<I>,
}
impl<'a, I, S, G> GeneratorIter<'a, I, S, G> {
pub fn new(generator: G, state: &'a mut S) -> Self {
Self {
generator,
state,
phantom: PhantomData,
}
}
}
impl<I, S, G> Iterator for GeneratorIter<'_, I, S, G>
where
G: Generator<I, S>,
{
type Item = I;
fn next(&mut self) -> Option<Self::Item> {
self.generator.generate(self.state).ok()
}
}
#[derive(Debug, Clone)]
pub struct RandBytesGenerator {
min_size: NonZeroUsize,
max_size: NonZeroUsize,
}
impl<S> Generator<BytesInput, S> for RandBytesGenerator
where
S: HasRand,
{
fn generate(&mut self, state: &mut S) -> Result<BytesInput, Error> {
let mut size = state
.rand_mut()
.between(self.min_size.get(), self.max_size.get());
size = max(size, 1);
let random_bytes: Vec<u8> = (0..size)
.map(|_| state.rand_mut().below(nonzero!(256)) as u8)
.collect();
Ok(BytesInput::new(random_bytes))
}
}
impl RandBytesGenerator {
#[must_use]
pub fn new(max_size: NonZeroUsize) -> Self {
Self {
min_size: nonzero!(1),
max_size,
}
}
#[must_use]
pub fn with_min_size(min_size: NonZeroUsize, max_size: NonZeroUsize) -> Self {
Self { min_size, max_size }
}
}
#[derive(Debug, Clone)]
pub struct RandPrintablesGenerator {
min_size: NonZeroUsize,
max_size: NonZeroUsize,
}
impl<S> Generator<BytesInput, S> for RandPrintablesGenerator
where
S: HasRand,
{
fn generate(&mut self, state: &mut S) -> Result<BytesInput, Error> {
let mut size = state
.rand_mut()
.between(self.min_size.get(), self.max_size.get());
size = max(size, 1);
let printables = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz \t\n!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".as_bytes();
let random_bytes: Vec<u8> = (0..size)
.map(|_| *state.rand_mut().choose(printables).unwrap())
.collect();
Ok(BytesInput::new(random_bytes))
}
}
impl RandPrintablesGenerator {
#[must_use]
pub fn new(max_size: NonZeroUsize) -> Self {
Self {
min_size: nonzero!(1),
max_size,
}
}
#[must_use]
pub fn with_min_size(min_size: NonZeroUsize, max_size: NonZeroUsize) -> Self {
Self { min_size, max_size }
}
}