dynamic_provider/
request_macro.rs1#![allow(unused_parens)]
2
3#[macro_export]
64macro_rules! request {
65 ($($token:tt)*) => {
66 $crate::__request_invoke! { $($token)* }
67 };
68}
69
70#[doc(hidden)]
71#[macro_export]
72macro_rules! __request_invoke {
73 (from $from:expr; in $($rest:tt)*) => {
74 $crate::__request_in! { @from = ($from); in $($rest)* }
75 };
76 (from $from:expr; $($rest:tt)*) => {
77 $crate::__request_body! {
78 @from = ($from);
79 @in = (_);
80 @tokens = { $($rest)* };
81 }
82 };
83}
84
85#[doc(hidden)]
86#[macro_export]
87macro_rules! __request_in {
88 (@from = $from:tt; in $($lt:lifetime),* $(,)?; $($rest:tt)* ) => {
89 $crate::__request_body! {
90 @from = $from;
91 @in = ($crate::Lt![$($lt),*]);
92 @tokens = { $($rest)* };
93 }
94 };
95 (@from = $from:tt; in $($lt:lifetime,)* .. $L:ty; $($rest:tt)* ) => {
96 $crate::__request_body! {
97 @from = $from;
98 @in = (Lt![$($lt,)* .. $L]);
99 @tokens = { $($rest)* };
100 }
101 };
102 (@from = $from:tt; in $L:ty; $($rest:tt)* ) => {
103 $crate::__request_body! {
104 @from = $from;
105 @in = ($L);
106 @tokens = { $($rest)* };
107 }
108 };
109}
110
111#[doc(hidden)]
112#[macro_export]
113macro_rules! __request_body {
114 {
115 @from = ($from:expr);
116 @in = ($L:ty);
117 @tokens = {
118 $($rest:tt)*
119 };
120 } => {
121 {
122 let mut _helper = $crate::__m::RequestHelper::<$L, _, _>::new($from);
123
124 $crate::__request_rules! {
125 @helper = _helper;
126 @tokens = { $($rest)* };
127 }
128 }
129 };
130}
131
132#[doc(hidden)]
133#[macro_export]
134macro_rules! __request_rules {
135 {
136 @helper = $helper:ident;
137 @tokens = {
138 else $pat:pat => $out:expr $(,)?
139 };
140 } => {
141 match $helper.finish() {
142 $crate::__m::Ok(_out) => _out,
143 $crate::__m::Err($pat) => $out,
144 }
145 };
146 {
147 @helper = $helper:ident;
148 @tokens = {
149 else => $out:expr $(,)?
150 };
151 } => {
152 match $helper.finish() {
153 $crate::__m::Ok(_out) => _out,
154 $crate::__m::Err(_) => $out,
155 }
156 };
157
158 {
159 @helper = $helper:ident;
160 @tokens = {
161 else $($rest:tt)*
162 };
163 } => {
164 $crate::__request_rules! {
165 @modifier = else;
166 @helper = $helper;
167 @tokens = { $($rest)* };
168 }
169 };
170
171 {
172 @helper = $helper:ident;
173 @tokens = {};
174 } => {
175 $helper.finish()
176 };
177
178 {
179 @helper = $helper:ident;
180 @tokens = {
181 ref mut $($rest:tt)*
182 };
183 } => {
184 $crate::__request_rules! {
185 @modifier = request_mut;
186 @helper = $helper;
187 @tokens = { $($rest)* };
188 }
189 };
190 {
191 @helper = $helper:ident;
192 @tokens = {
193 ref $($rest:tt)*
194 };
195 } => {
196 $crate::__request_rules! {
197 @modifier = request_ref;
198 @helper = $helper;
199 @tokens = { $($rest)* };
200 }
201 };
202 {
203 @helper = $helper:ident;
204 @tokens = {
205 tag $($rest:tt)*
206 };
207 } => {
208 $crate::__request_rules! {
209 @modifier = request;
210 @helper = $helper;
211 @tokens = { $($rest)* };
212 }
213 };
214 {
215 @helper = $helper:ident;
216 @tokens = {
217 $($rest:tt)*
218 };
219 } => {
220 $crate::__request_rules! {
221 @modifier = request_value;
222 @helper = $helper;
223 @tokens = { $($rest)* };
224 }
225 };
226
227 {
228 @modifier = $method:ident;
229 @helper = $helper:ident;
230 @tokens = {
231 $pat:tt: $Ty:ty
232 $(where arg <- $arg:expr)?
233 => $out:expr
234 $(, $($rest:tt)*)?
235 };
236 } => {
237 $helper = match $helper.$method::<$Ty>(($($arg)?)) {
238 $crate::__m::Ok($pat) => $crate::__m::RequestHelper::from_out($out),
239 $crate::__m::Err(_helper) => _helper,
240 };
241
242 $crate::__request_rules! {
243 @helper = $helper;
244 @tokens = { $($($rest)*)? };
245 }
246 };
247
248 {
249 @modifier = $modifier:tt;
250 @helper = $helper:ident;
251 @tokens = {
252 $pat:pat => $($rest:tt)*
253 };
254 } => {
255 $crate::__request_rules! {
256 @modifier = $modifier;
257 @helper = $helper;
258 @tokens = {
259 ($pat): _ => $($rest)*
260 };
261 }
262 };
263 {
264 @modifier = $modifier:tt;
265 @helper = $helper:ident;
266 @tokens = {
267 $($pat1:ident)* $(::$pat2:ident)* $({$($pat3:tt)*})? $(($($pat4:tt)*))?
268 : $Ty:ty
269 $(where $key:ident = $value:expr)?
270 => $($rest:tt)*
271 };
272 } => {
273 $crate::__request_rules! {
274 @modifier = $modifier;
275 @helper = $helper;
276 @tokens = {
277 ( $($pat1)* $(::$pat2)* $({ $($pat3)* })? $(( $($pat4)* ))? )
278 : $Ty
279 $(where $key = $value)?
280 => $($rest)*
281 };
282 }
283 };
284}
285
286#[cfg(test)]
287mod test {
288 use crate::{Lt, ProvideRef, QueryUsing};
289
290 #[test]
291 fn macro_usage() {
292 crate::define_tag! {
293 tag Foo: for<'x, 'y, 'input> &'input i32 => i32;
294 }
295 fn explicit_lts<'x, 'y>(
296 p: &'x mut dyn for<'i> crate::ProvideRef<crate::Lt!['y, 'i]>,
297 ) -> i32 {
298 let a = 0;
299 let b = 1;
300
301 request! {
302 from &mut *p;
303 in 'x, 'y, '_;
304 x: i32 => x,
305 tag x: Foo where arg <- &b => x + a,
306 ref mut x => *x,
307 ref y => *y,
308 else => 0,
309 }
310 }
311
312 fn implicit_lts(p: &mut dyn for<'i> crate::ProvideRef<crate::Lt!['_, 'i]>) -> i32 {
313 let a = 0;
314 let b = 1;
315
316 request! {
317 from &mut *p;
318 x: i32 => x,
319 tag x: Foo where arg <- &b => x + a,
320 ref mut x => *x,
321 ref y => *y,
322 else => 0,
323 }
324 }
325
326 fn check_both(p: &mut dyn for<'i> crate::ProvideRef<crate::Lt!['_, 'i]>) -> i32 {
327 let out1 = explicit_lts(p);
328 let out2 = implicit_lts(p);
329 assert_eq!(out1, out2);
330 out1
331 }
332
333 #[allow(clippy::type_complexity)]
334 struct CustomProvide(
335 i32,
336 for<'q, 'x, 'y, 'z> fn(
337 QueryUsing<'q, &'x mut i32, Lt!['x, 'y, 'z]>,
338 ) -> QueryUsing<'q, &'x mut i32, Lt!['x, 'y, 'z]>,
339 );
340
341 impl ProvideRef<Lt!['_, '_]> for CustomProvide {
342 fn provide_mut<'this>(&'this mut self, query: &mut crate::Query<Lt!['this, '_, '_]>) {
343 self.1(query.using(&mut self.0)).finish();
344 }
345 }
346
347 let mut p_value = CustomProvide(1_i32, |q| q.put_value(|x| *x));
348 assert_eq!(check_both(&mut p_value), 1);
349
350 let mut p_tag = CustomProvide(1_i32, |q| q.put_with_arg::<Foo>(|arg, x| *arg + *x));
351 assert_eq!(check_both(&mut p_tag), 2);
352
353 let mut p_ref = CustomProvide(3_i32, |q| q.put_ref(|x| x));
354 assert_eq!(check_both(&mut p_ref), 3);
355
356 let mut p_mut = CustomProvide(4_i32, |q| q.put_mut(|x| x));
357 assert_eq!(check_both(&mut p_mut), 4);
358
359 assert_eq!(check_both(&mut ()), 0);
360 }
361}