random_number_macro_impl/
lib.rs1use proc_macro::TokenStream;
2use proc_macro_hack::proc_macro_hack;
3use quote::quote;
4use syn::{
5 parse::{Parse, ParseStream},
6 parse_macro_input, Expr, RangeLimits, Token,
7};
8
9struct RandomBuilder {
10 min: Option<Box<Expr>>,
11 max: Option<Box<Expr>>,
12 rng: Option<Box<Expr>>,
13 exclusive: bool,
14 cmp: bool,
15}
16
17impl Parse for RandomBuilder {
18 fn parse(input: ParseStream) -> Result<Self, syn::Error> {
19 if input.is_empty() {
20 Ok(RandomBuilder {
21 min: None,
22 max: None,
23 rng: None,
24 exclusive: false,
25 cmp: false,
26 })
27 } else {
28 let expr: Expr = input.parse()?;
29
30 if let Expr::Range(range) = expr {
31 let exclusive = match range.limits {
32 RangeLimits::HalfOpen(_) => true,
33 RangeLimits::Closed(_) => false,
34 };
35
36 let min = range.start;
37 let max = range.end;
38
39 if input.is_empty() {
40 Ok(RandomBuilder {
41 min,
42 max,
43 rng: None,
44 exclusive,
45 cmp: false,
46 })
47 } else {
48 input.parse::<Token!(,)>()?;
49
50 let expr: Expr = input.parse()?;
51
52 Ok(RandomBuilder {
53 min,
54 max,
55 rng: Some(Box::new(expr)),
56 exclusive,
57 cmp: false,
58 })
59 }
60 } else if input.lookahead1().peek(Token!(,)) {
61 input.parse::<Token!(,)>()?;
62
63 let expr2: Expr = input.parse()?;
64
65 if input.is_empty() {
66 Ok(RandomBuilder {
67 min: Some(Box::from(expr)),
68 max: Some(Box::from(expr2)),
69 rng: None,
70 exclusive: false,
71 cmp: true,
72 })
73 } else {
74 input.parse::<Token!(,)>()?;
75
76 let expr3: Expr = input.parse()?;
77
78 Ok(RandomBuilder {
79 min: Some(Box::from(expr)),
80 max: Some(Box::from(expr2)),
81 rng: Some(Box::new(expr3)),
82 exclusive: false,
83 cmp: true,
84 })
85 }
86 } else {
87 Ok(RandomBuilder {
88 min: None,
89 max: None,
90 rng: Some(Box::new(expr)),
91 exclusive: false,
92 cmp: false,
93 })
94 }
95 }
96 }
97}
98
99#[proc_macro_hack]
100pub fn random(input: TokenStream) -> TokenStream {
101 let rb = parse_macro_input!(input as RandomBuilder);
102
103 let random = match rb.min.as_ref() {
104 Some(min) => match rb.max.as_ref() {
105 Some(max) => {
106 if rb.exclusive {
107 match rb.rng.as_ref() {
108 Some(rng) => {
109 quote! {
110 $crate::random_exclusively_with_rng(#min, #max, &mut #rng)
111 }
112 },
113 None => {
114 quote! {
115 $crate::random_exclusively(#min, #max)
116 }
117 },
118 }
119 } else if rb.cmp {
120 match rb.rng.as_ref() {
121 Some(rng) => {
122 quote! {
123 $crate::random_inclusively_cmp_with_rng(#min, #max, &mut #rng)
124 }
125 },
126 None => {
127 quote! {
128 $crate::random_inclusively_cmp(#min, #max)
129 }
130 },
131 }
132 } else {
133 match rb.rng.as_ref() {
134 Some(rng) => {
135 quote! {
136 $crate::random_inclusively_with_rng(#min, #max, &mut #rng)
137 }
138 },
139 None => {
140 quote! {
141 $crate::random_inclusively(#min, #max)
142 }
143 },
144 }
145 }
146 },
147 None => match rb.rng.as_ref() {
148 Some(rng) => {
149 quote! {
150 $crate::random_at_least_with_rng(#min, &mut #rng)
151 }
152 },
153 None => {
154 quote! {
155 $crate::random_at_least(#min)
156 }
157 },
158 },
159 },
160 None => match rb.max.as_ref() {
161 Some(max) => {
162 if rb.exclusive {
163 match rb.rng.as_ref() {
164 Some(rng) => {
165 quote! {
166 $crate::random_at_most_exclusively_with_rng(#max, &mut #rng)
167 }
168 },
169 None => {
170 quote! {
171 $crate::random_at_most_exclusively(#max)
172 }
173 },
174 }
175 } else {
176 match rb.rng.as_ref() {
177 Some(rng) => {
178 quote! {
179 $crate::random_at_most_with_rng(#max, &mut #rng)
180 }
181 },
182 None => {
183 quote! {
184 $crate::random_at_most(#max)
185 }
186 },
187 }
188 }
189 },
190 None => match rb.rng.as_ref() {
191 Some(rng) => {
192 quote! {
193 $crate::random_with_rng(&mut #rng)
194 }
195 },
196 None => {
197 quote! {
198 $crate::random()
199 }
200 },
201 },
202 },
203 };
204
205 random.into()
206}
207
208struct RandomFillBuilder {
211 out: Box<Expr>,
212 rb: RandomBuilder,
213}
214
215impl Parse for RandomFillBuilder {
216 fn parse(input: ParseStream) -> Result<Self, syn::Error> {
217 let expr: Expr = input.parse()?;
218
219 let out = Box::from(expr);
220
221 if input.lookahead1().peek(Token!(,)) {
222 input.parse::<Token!(,)>()?;
223 }
224
225 let rb: RandomBuilder = input.parse()?;
226
227 Ok(RandomFillBuilder {
228 out,
229 rb,
230 })
231 }
232}
233
234#[proc_macro_hack::proc_macro_hack]
235pub fn random_fill(input: TokenStream) -> TokenStream {
236 let rfb = parse_macro_input!(input as RandomFillBuilder);
237
238 let out = rfb.out;
239
240 let rb = rfb.rb;
241
242 let random_fill = match rb.min.as_ref() {
243 Some(min) => match rb.max.as_ref() {
244 Some(max) => {
245 if rb.exclusive {
246 match rb.rng.as_ref() {
247 Some(rng) => {
248 quote! {
249 $crate::random_fill_exclusively_with_rng(#out.as_mut(), #min, #max, &mut #rng)
250 }
251 },
252 None => {
253 quote! {
254 $crate::random_fill_exclusively(#out.as_mut(), #min, #max)
255 }
256 },
257 }
258 } else if rb.cmp {
259 match rb.rng.as_ref() {
260 Some(rng) => {
261 quote! {
262 $crate::random_fill_inclusively_cmp_with_rng(#out.as_mut(), #min, #max, &mut #rng)
263 }
264 },
265 None => {
266 quote! {
267 $crate::random_fill_inclusively_cmp(#out.as_mut(), #min, #max)
268 }
269 },
270 }
271 } else {
272 match rb.rng.as_ref() {
273 Some(rng) => {
274 quote! {
275 $crate::random_fill_inclusively_with_rng(#out.as_mut(), #min, #max, &mut #rng)
276 }
277 },
278 None => {
279 quote! {
280 $crate::random_fill_inclusively(#out.as_mut(), #min, #max)
281 }
282 },
283 }
284 }
285 },
286 None => match rb.rng.as_ref() {
287 Some(rng) => {
288 quote! {
289 $crate::random_fill_at_least_with_rng(#out.as_mut(), #min, &mut #rng)
290 }
291 },
292 None => {
293 quote! {
294 $crate::random_fill_at_least(#out.as_mut(), #min)
295 }
296 },
297 },
298 },
299 None => match rb.max.as_ref() {
300 Some(max) => {
301 if rb.exclusive {
302 match rb.rng.as_ref() {
303 Some(rng) => {
304 quote! {
305 $crate::random_fill_at_most_exclusively_with_rng(#out.as_mut(), #max, &mut #rng)
306 }
307 },
308 None => {
309 quote! {
310 $crate::random_fill_at_most_exclusively(#out.as_mut(), #max)
311 }
312 },
313 }
314 } else {
315 match rb.rng.as_ref() {
316 Some(rng) => {
317 quote! {
318 $crate::random_fill_at_most_with_rng(#out.as_mut(), #max, &mut #rng)
319 }
320 },
321 None => {
322 quote! {
323 $crate::random_fill_at_most(#out.as_mut(), #max)
324 }
325 },
326 }
327 }
328 },
329 None => match rb.rng.as_ref() {
330 Some(rng) => {
331 quote! {
332 $crate::random_fill_with_rng(#out.as_mut(), &mut #rng)
333 }
334 },
335 None => {
336 quote! {
337 $crate::random_fill(#out.as_mut())
338 }
339 },
340 },
341 },
342 };
343
344 random_fill.into()
345}