use alloc::vec::Vec;
use core::cmp::min;
use crate::{
bolts::rands::Rand,
inputs::{bytes::BytesInput, Input},
Error,
};
const DUMMY_BYTES_MAX: usize = 64;
pub trait Generator<I, R>
where
I: Input,
R: Rand,
{
fn generate(&mut self, rand: &mut R) -> Result<I, Error>;
fn generate_dummy(&self) -> I;
}
#[derive(Clone, Debug)]
pub struct RandBytesGenerator {
max_size: usize,
}
impl<R> Generator<BytesInput, R> for RandBytesGenerator
where
R: Rand,
{
fn generate(&mut self, rand: &mut R) -> Result<BytesInput, Error> {
let mut size = rand.below(self.max_size as u64);
if size == 0 {
size = 1;
}
let random_bytes: Vec<u8> = (0..size).map(|_| rand.below(256) as u8).collect();
Ok(BytesInput::new(random_bytes))
}
fn generate_dummy(&self) -> BytesInput {
let size = min(self.max_size, DUMMY_BYTES_MAX);
BytesInput::new(vec![0; size])
}
}
impl RandBytesGenerator {
#[must_use]
pub fn new(max_size: usize) -> Self {
Self { max_size }
}
}
#[derive(Clone, Debug)]
pub struct RandPrintablesGenerator {
max_size: usize,
}
impl<R> Generator<BytesInput, R> for RandPrintablesGenerator
where
R: Rand,
{
fn generate(&mut self, rand: &mut R) -> Result<BytesInput, Error> {
let mut size = rand.below(self.max_size as u64);
if size == 0 {
size = 1;
}
let printables = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz \t\n!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".as_bytes();
let random_bytes: Vec<u8> = (0..size).map(|_| *rand.choose(printables)).collect();
Ok(BytesInput::new(random_bytes))
}
fn generate_dummy(&self) -> BytesInput {
let size = min(self.max_size, DUMMY_BYTES_MAX);
BytesInput::new(vec![0_u8; size])
}
}
impl RandPrintablesGenerator {
#[must_use]
pub fn new(max_size: usize) -> Self {
Self { max_size }
}
}