use std::iter::FromIterator;
use rand::{thread_rng, Rng};
use crate::{Config, Spongemock};
impl Spongemock for String {
fn mock(&mut self, config: &Config) {
if self.is_empty() {
return;
}
let mut rng = thread_rng();
let mut chars = vec![];
let mut prev_upper;
let mut prev_prev_upper = true;
let mut transform_char = |c: char, prob: f64, inverse: bool| {
let gen_bool = rng.gen_bool(prob);
let gen_bool = if inverse { !gen_bool } else { gen_bool };
if gen_bool {
chars.extend(c.to_uppercase());
} else {
chars.extend(c.to_lowercase());
};
gen_bool
};
prev_upper = transform_char(self.chars().next().unwrap(), config.first_upper, false);
if self.len() != 1 {
if prev_upper {
prev_prev_upper = prev_upper;
prev_upper =
transform_char(self.chars().nth(1).unwrap(), config.upper_to_lower, true);
} else {
prev_upper =
transform_char(self.chars().nth(1).unwrap(), config.lower_to_upper, false);
}
}
for c in self.as_mut().chars().skip(2) {
if prev_upper == prev_prev_upper {
if prev_upper {
prev_prev_upper = prev_upper;
prev_upper = transform_char(c, config.upper_upper_to_lower, true);
} else {
prev_prev_upper = prev_upper;
prev_upper = transform_char(c, config.lower_lower_to_upper, false);
}
} else if prev_upper {
prev_prev_upper = prev_upper;
prev_upper = transform_char(c, config.upper_to_lower, true);
} else {
prev_prev_upper = prev_upper;
prev_upper = transform_char(c, config.lower_to_upper, false);
}
}
*self = String::from_iter(chars);
}
}