use super::*;
#[derive(Clone, Debug, Default)]
pub struct CStringMutator {
_private: (),
}
pub fn c_string() -> CStringMutator {
CStringMutator { _private: () }
}
fn gen_nonzero_byte(ctx: &mut Context) -> u8 {
let b = ctx.rng().gen_u8();
if b == 0 {
1
} else {
b
}
}
impl Mutate<alloc::ffi::CString> for CStringMutator {
#[inline]
fn mutation_count(
&self,
value: &alloc::ffi::CString,
shrink: bool,
) -> core::option::Option<u32> {
let mut count = 0u32;
count += !value.as_bytes().is_empty() as u32;
count += !shrink as u32;
count += !value.as_bytes().is_empty() as u32;
Some(count)
}
#[inline]
fn mutate(&mut self, c: &mut Candidates, value: &mut alloc::ffi::CString) -> Result<()> {
let bytes = value.clone().into_bytes();
if !bytes.is_empty() {
c.mutation(|ctx| {
let mut bytes = value.clone().into_bytes();
let index = ctx.rng().gen_index(bytes.len()).unwrap();
bytes[index] = gen_nonzero_byte(ctx);
*value = alloc::ffi::CString::new(bytes).unwrap();
Ok(())
})?;
}
if !c.shrink() {
c.mutation(|ctx| {
let mut bytes = value.clone().into_bytes();
let index = ctx.rng().gen_index(bytes.len() + 1).unwrap();
bytes.insert(index, gen_nonzero_byte(ctx));
*value = alloc::ffi::CString::new(bytes).unwrap();
Ok(())
})?;
}
if !bytes.is_empty() {
c.mutation(|ctx| {
let mut bytes = value.clone().into_bytes();
let index = ctx.rng().gen_index(bytes.len()).unwrap();
bytes.remove(index);
*value = alloc::ffi::CString::new(bytes).unwrap();
Ok(())
})?;
}
Ok(())
}
}
impl Generate<alloc::ffi::CString> for CStringMutator {
#[inline]
fn generate(&mut self, ctx: &mut Context) -> Result<alloc::ffi::CString> {
let len = ctx.rng().inner().gen_range(0..=20);
let bytes: alloc::vec::Vec<u8> = (0..len).map(|_| gen_nonzero_byte(ctx)).collect();
Ok(alloc::ffi::CString::new(bytes).unwrap())
}
}
impl DefaultMutate for alloc::ffi::CString {
type DefaultMutate = CStringMutator;
}