extern crate proc_macro;
use proc_macro::TokenStream;
use core::mem;
fn randomize<T: Copy>() -> T {
let mut val = mem::MaybeUninit::<T>::uninit();
let slice = unsafe {
core::slice::from_raw_parts_mut(val.as_mut_ptr() as *mut mem::MaybeUninit<u8>, core::mem::size_of::<T>())
};
getrandom::fill_uninit(slice).expect("Failed to generate random number");
unsafe {
val.assume_init()
}
}
fn randomize_type(path: &str) -> Option<String> {
let res = if path.eq_ignore_ascii_case("u8"){
let res = randomize::<u8>();
format!("{}u8", res)
} else if path.eq_ignore_ascii_case("i8") {
let res = randomize::<i8>();
format!("{}i8", res)
} else if path.eq_ignore_ascii_case("u16") {
let res = randomize::<u16>();
format!("{}u16", res)
} else if path.eq_ignore_ascii_case("i16") {
let res = randomize::<i16>();
format!("{}i16", res)
} else if path.eq_ignore_ascii_case("u32") {
let res = randomize::<u32>();
format!("{}u32", res)
} else if path.eq_ignore_ascii_case("i32") {
let res = randomize::<i32>();
format!("{}i32", res)
} else if path.eq_ignore_ascii_case("u64") {
let res = randomize::<u64>();
format!("{}u64", res)
} else if path.eq_ignore_ascii_case("i64") {
let res = randomize::<i64>();
format!("{}i64", res)
} else if path.eq_ignore_ascii_case("u128") {
let res = randomize::<u128>();
format!("{}u128", res)
} else if path.eq_ignore_ascii_case("i128") {
let res = randomize::<i128>();
format!("{}i128", res)
} else if path.eq_ignore_ascii_case("usize") {
let res = randomize::<usize>();
format!("{}usize", res)
} else if path.eq_ignore_ascii_case("isize") {
let res = randomize::<isize>();
format!("{}isize", res)
} else {
return None
};
Some(res)
}
#[proc_macro]
pub fn random(input: TokenStream) -> TokenStream {
let input = input.to_string();
let input = input.trim();
if input.is_empty() {
panic!("Empty input :(");
} else if input.starts_with('[') {
if !input.ends_with(']') {
panic!("'{}' is missing right bracket", input);
}
let array_content = input[1..input.len()-1].trim();
if array_content.is_empty() {
panic!("just empty brackets? Did you mean array?");
}
let mut split = array_content.splitn(2, ';');
let typ = split.next().unwrap().trim();
if randomize_type(typ).is_none() {
panic!("'{}' is unsupported", typ);
}
let num = split.next().expect("Missing ';' in array type").trim();
let num: usize = num.parse().expect("Array type size is invalid as usize");
let mut result = "[".to_owned();
if num > 0 {
for _ in 0..num {
result.push_str(randomize_type(typ).unwrap().as_str());
result.push(',');
}
result.pop();
}
result.push(']');
result.parse().unwrap()
} else if let Some(result) = randomize_type(input) {
result.parse().unwrap()
} else {
panic!("Unsupported type");
}
}