1use std::sync::atomic::{AtomicU32, Ordering::Relaxed};
2use std::sync::Once;
3
4static DEFAULT_SEED: AtomicU32 = AtomicU32::new(0);
5static INIT: Once = Once::new();
6
7const DEFAULT_BUF_SIZE: usize = 1024 * 1024;
8
9mod bindings;
10
11fn init() {
14 unsafe {
15 bindings::radamsa_init();
16 }
17}
18
19pub fn generate(
26 input: &Vec<u8>,
27 seed: Option<u32>,
28 maxsize: Option<usize>,
29) -> Vec<u8> {
30 INIT.call_once(init);
31 let max_size_val = maxsize.unwrap_or(DEFAULT_BUF_SIZE);
32 let mut out_vec = vec![0u8; max_size_val];
33 let seed_val = match seed {
34 Some(seed) => seed,
35 None => DEFAULT_SEED.fetch_add(1, Relaxed),
36 };
37 let outlen = unsafe {
38 bindings::radamsa(
39 input.as_ptr(),
40 input.len(),
41 out_vec.as_mut_ptr(),
42 max_size_val,
43 seed_val,
44 )
45 };
46 assert!(outlen <= max_size_val);
47 out_vec.truncate(outlen);
48 out_vec
49}
50
51pub fn mutate(input: &mut Vec<u8>, seed: Option<u32>) -> usize {
62 INIT.call_once(init);
63 let seed_val = match seed {
64 Some(seed) => seed,
65 None => DEFAULT_SEED.fetch_add(1, Relaxed),
66 };
67 let outlen = unsafe {
68 bindings::radamsa_inplace(
69 input.as_mut_ptr(),
70 input.len(),
71 input.len(),
72 seed_val,
73 )
74 };
75 outlen
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 #[test]
82 fn test_generator() {
83 let start_val = "hello world".as_bytes().to_vec();
84 for i in 0..100 {
85 let output = generate(&start_val, None, None);
86 println!("output {} {}", i, String::from_utf8_lossy(&output));
87 }
88 }
89
90 #[test]
91 fn test_mutator() {
92 let mut mut_vec = "hello world".as_bytes().to_vec();
93 mut_vec.extend(vec![0u8; 1000].iter().copied());
94 for i in 0..100 {
95 mutate(&mut mut_vec, None);
96 println!("output {} \"{}\"", i, String::from_utf8_lossy(&mut_vec));
97 }
98 }
99}