use super::*;
use std::ffi::OsString;
#[derive(Clone, Debug, Default)]
pub struct OsStringMutator {
string_mutator: StringMutator<Char>,
}
pub fn os_string() -> OsStringMutator {
OsStringMutator::default()
}
impl Mutate<OsString> for OsStringMutator {
#[inline]
fn mutation_count(&self, value: &OsString, shrink: bool) -> core::option::Option<u32> {
let can_remove = value.to_str().map_or(false, |s| !s.is_empty());
let mut count = 0u32;
count += can_remove as u32;
count += !shrink as u32;
count += !value.is_empty() as u32;
count += 4;
Some(count)
}
#[inline]
fn mutate(&mut self, c: &mut Candidates, value: &mut OsString) -> Result<()> {
if let Some(s) = value.to_str() {
let len = s.len();
if len != 0 {
c.mutation(|ctx| {
let i = ctx.rng().gen_index(len).unwrap();
let s: alloc::string::String = value
.to_str()
.unwrap()
.char_indices()
.filter_map(|(j, c)| if i == j { None } else { Some(c) })
.collect();
*value = OsString::from(s);
Ok(())
})?;
}
}
if !c.shrink() {
c.mutation(|ctx| {
let ch = ctx.rng().gen_char();
let mut buf = [0u8; 4];
let s = ch.encode_utf8(&mut buf);
value.push(s);
Ok(())
})?;
}
if !value.is_empty() {
c.mutation(|_ctx| {
*value = OsString::new();
Ok(())
})?;
}
c.mutation(|_ctx| {
*value = OsString::from(".");
Ok(())
})?;
c.mutation(|_ctx| {
*value = OsString::from("..");
Ok(())
})?;
c.mutation(|_ctx| {
*value = OsString::from("/");
Ok(())
})?;
c.mutation(|_ctx| {
*value = OsString::from("\\");
Ok(())
})?;
Ok(())
}
}
impl Generate<OsString> for OsStringMutator {
#[inline]
fn generate(&mut self, ctx: &mut Context) -> Result<OsString> {
let s = self.string_mutator.generate(ctx)?;
Ok(OsString::from(s))
}
}
impl DefaultMutate for OsString {
type DefaultMutate = OsStringMutator;
}