use std::sync::atomic::{AtomicU32, Ordering::Relaxed};
use std::sync::Once;
static DEFAULT_SEED: AtomicU32 = AtomicU32::new(0);
static INIT: Once = Once::new();
const DEFAULT_BUF_SIZE: usize = 1024 * 1024;
mod bindings;
fn init() {
unsafe {
bindings::radamsa_init();
}
}
pub fn generate(
input: &Vec<u8>,
seed: Option<u32>,
maxsize: Option<usize>,
) -> Vec<u8> {
INIT.call_once(init);
let max_size_val = maxsize.unwrap_or(DEFAULT_BUF_SIZE);
let mut out_vec = vec![0u8; max_size_val];
let seed_val = match seed {
Some(seed) => seed,
None => DEFAULT_SEED.fetch_add(1, Relaxed),
};
let outlen = unsafe {
bindings::radamsa(
input.as_ptr(),
input.len(),
out_vec.as_mut_ptr(),
max_size_val,
seed_val,
)
};
assert!(outlen <= max_size_val);
out_vec.truncate(outlen);
out_vec
}
pub fn mutate(input: &mut Vec<u8>, seed: Option<u32>) -> usize {
INIT.call_once(init);
let seed_val = match seed {
Some(seed) => seed,
None => DEFAULT_SEED.fetch_add(1, Relaxed),
};
let outlen = unsafe {
bindings::radamsa_inplace(
input.as_mut_ptr(),
input.len(),
input.len(),
seed_val,
)
};
outlen
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generator() {
let start_val = "hello world".as_bytes().to_vec();
for i in 0..100 {
let output = generate(&start_val, None, None);
println!("output {} {}", i, String::from_utf8_lossy(&output));
}
}
#[test]
fn test_mutator() {
let mut mut_vec = "hello world".as_bytes().to_vec();
mut_vec.extend(vec![0u8; 1000].iter().copied());
for i in 0..100 {
mutate(&mut mut_vec, None);
println!("output {} \"{}\"", i, String::from_utf8_lossy(&mut_vec));
}
}
}