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