1extern crate proc_macro;
40
41use proc_macro::TokenStream;
42use getrandom::getrandom_uninit;
43
44use core::mem;
45
46fn randomize<T: Copy>() -> T {
47 let mut val = mem::MaybeUninit::<T>::uninit();
48 let slice = unsafe {
49 core::slice::from_raw_parts_mut(val.as_mut_ptr() as *mut mem::MaybeUninit<u8>, core::mem::size_of::<T>())
50 };
51
52 getrandom_uninit(slice).expect("Failed to generate random number");
53 unsafe {
54 val.assume_init()
55 }
56}
57
58fn randomize_type(path: &str) -> Option<String> {
59 let res = if path.eq_ignore_ascii_case("u8"){
60 let res = randomize::<u8>();
61 format!("{}u8", res)
62 } else if path.eq_ignore_ascii_case("i8") {
63 let res = randomize::<i8>();
64 format!("{}i8", res)
65 } else if path.eq_ignore_ascii_case("u16") {
66 let res = randomize::<u16>();
67 format!("{}u16", res)
68 } else if path.eq_ignore_ascii_case("i16") {
69 let res = randomize::<i16>();
70 format!("{}i16", res)
71 } else if path.eq_ignore_ascii_case("u32") {
72 let res = randomize::<u32>();
73 format!("{}u32", res)
74 } else if path.eq_ignore_ascii_case("i32") {
75 let res = randomize::<i32>();
76 format!("{}i32", res)
77 } else if path.eq_ignore_ascii_case("u64") {
78 let res = randomize::<u64>();
79 format!("{}u64", res)
80 } else if path.eq_ignore_ascii_case("i64") {
81 let res = randomize::<i64>();
82 format!("{}i64", res)
83 } else if path.eq_ignore_ascii_case("u128") {
84 let res = randomize::<u128>();
85 format!("{}u128", res)
86 } else if path.eq_ignore_ascii_case("i128") {
87 let res = randomize::<i128>();
88 format!("{}i128", res)
89 } else if path.eq_ignore_ascii_case("usize") {
90 let res = randomize::<usize>();
91 format!("{}usize", res)
92 } else if path.eq_ignore_ascii_case("isize") {
93 let res = randomize::<isize>();
94 format!("{}isize", res)
95 } else {
96 return None
97 };
98
99 Some(res)
100}
101
102#[proc_macro]
103pub fn random(input: TokenStream) -> TokenStream {
104 let input = input.to_string();
105 let input = input.trim();
106
107 if input.is_empty() {
108 panic!("Empty input :(");
109 } else if input.starts_with('[') {
110 if !input.ends_with(']') {
111 panic!("'{}' is missing right bracket", input);
112 }
113
114 let array_content = input[1..input.len()-1].trim();
115 if array_content.is_empty() {
116 panic!("just empty brackets? Did you mean array?");
117 }
118
119 let mut split = array_content.splitn(2, ';');
120 let typ = split.next().unwrap().trim();
121
122 if randomize_type(typ).is_none() {
123 panic!("'{}' is unsupported", typ);
124 }
125
126 let num = split.next().expect("Missing ';' in array type").trim();
127 let num: usize = num.parse().expect("Array type size is invalid as usize");
128
129 let mut result = "[".to_owned();
130 if num > 0 {
131 for _ in 0..num {
132 result.push_str(randomize_type(typ).unwrap().as_str());
133 result.push(',');
134 }
135 result.pop();
136 }
137 result.push(']');
138
139 result.parse().unwrap()
140 } else if let Some(result) = randomize_type(input) {
141 return result.parse().unwrap()
142 } else {
143 panic!("Unsupported type");
144 }
145}