using/
lib.rs

1//! This crate provides the [`using`] macro designed to simplify writing and using builders by
2//! providing [method cascading](https://en.wikipedia.org/wiki/Method_cascading):
3//!
4//! ```
5//! # use using::using;
6//! #[derive(Debug, Copy, Clone)]
7//! struct Vec3 {
8//!     x: f32,
9//!     y: f32,
10//!     z: f32,
11//! }
12//!
13//! #[derive(Default, Debug, Copy, Clone)]
14//! struct Vec3Builder {
15//!     x: Option<f32>,
16//!     y: Option<f32>,
17//!     z: Option<f32>,
18//! }
19//!
20//! impl Vec3Builder {
21//!     pub fn x(&mut self, x: f32) {
22//!         self.x = Some(x);
23//!     }
24//!
25//!     pub fn y(&mut self, y: f32) {
26//!         self.y = Some(y);
27//!     }
28//!
29//!     pub fn z(&mut self, z: f32) {
30//!         self.z = Some(z);
31//!     }
32//!
33//!     //this also works with `self` instead of `&mut self`
34//!     pub fn build(&mut self) -> Vec3 {
35//!         Vec3 {
36//!             x: self.x.unwrap(),
37//!             y: self.y.unwrap(),
38//!             z: self.z.unwrap(),
39//!         }
40//!     }
41//! }
42//!
43//! let vec3 = using!(Vec3Builder::default() => {
44//!     .x(4.27);
45//!     .y(9.71);
46//!     .z(13.37);
47//!     .build()
48//! });
49//!
50//! // Generated code:
51//! //
52//! // let vec3 = {
53//! //     let mut target = Vec3Builder::default();
54//! //     target.x(4.27);
55//! //     target.y(9.71);
56//! //     target.z(13.37);
57//! //     target.build()
58//! // };
59//! ```
60//!
61//! The idea is that instead of implementing builders as fluid interfaces that allow method
62//! chaining (i.e. each method returning `&mut Self` or `Self`), we implement our builder with
63//! simple setter methods and use it with the [`using`] macro, which gives us the ergonomics of
64//! conventional builders without having to implement the builder as a fluid interface.
65//!
66//! The macro is not bound to builders: it has no requirements on the type, therefore we can use it
67//! on basically anything:
68//!
69//! ```
70//! # use std::collections::HashMap;
71//! # use using::using;
72//! let map = using!(HashMap::new() => {
73//!     .insert("a", 41);
74//!     .insert("b", 971);
75//! });
76//! ```
77//!
78//! ```
79//! # use using::using;
80//! let hello_world = using!(Vec::new() => {
81//!     .push("Hello");
82//!     .push("World!");
83//!     .join(", ")
84//! });
85//! assert_eq!(hello_world, "Hello, World!");
86//! ```
87//!
88//! # Motivation
89//!
90//! The idea for this crate came from implementing the builder pattern in a personal project. In
91//! Rust, there are three main approaches for designing builder structs:
92//!
93//! * All methods taking `self` and returning `Self`:
94//!
95//!   ```ignore
96//!   impl SomeBuilder {
97//!       pub fn new() -> Self { ... }
98//!       pub fn x(self, arg: T) -> Self { ... }
99//!       pub fn y(self, arg: U) -> Self { ... }
100//!       pub fn z(self, arg: V) -> Self { ... }
101//!       pub fn build(self) -> Something { ... }
102//!   }
103//!   ```
104//!
105//!   The advantage of this method is that when building the final object, the fields can be moved
106//!   out of the builder. One disadvantage of this method is that using the builder in more
107//!   complicated ways can become quite verbose: if a method must be called inside an `if`
108//!   statement or a loop or if the builder must be passed to a function, the builder has to be
109//!   stored in a mutable variable and re-assigned everytime:
110//!
111//!   ```ignore
112//!   let mut builder = SomeBuilder::new()
113//!       .x(...)
114//!       .y(...);
115//!   if some_condition {
116//!       builder = builder.z(...);
117//!   }
118//!   if some_other_condition {
119//!       builder = some_function(builder);
120//!   }
121//!   let thing = builder.build();
122//!   ```
123//!
124//!   Also, the builder methods are quite verbose since they have to return `self`.
125//!
126//! * All methods taking `&mut self` and returning `&mut Self`:
127//!
128//!   ```ignore
129//!   impl SomeBuilder {
130//!       pub fn new() -> Self { ... }
131//!       pub fn x(&mut self, arg: T) -> &mut Self { ... }
132//!       pub fn y(&mut self, arg: U) -> &mut Self { ... }
133//!       pub fn z(&mut self, arg: V) -> &mut Self { ... }
134//!       pub fn build(&mut self) -> Something { ... }
135//!   }
136//!   ```
137//!
138//!   This improves the disadvantage of the first method with respect to more complicated
139//!   use-cases, because there are no re-assignments:
140//!
141//!   ```ignore
142//!   let mut builder = SomeBuilder::new()
143//!       .x(...)
144//!       .y(...);
145//!   if some_condition {
146//!       builder.z(...);
147//!   }
148//!   if some_other_condition {
149//!       some_function(&mut builder);
150//!   }
151//!   let thing = builder.build();
152//!   ```
153//!
154//!   However, with this method, the `build` method cannot take `self`, otherwise method chaining
155//!   does not work (except we require a call to `clone` or something similar, which is not really
156//!   intuitive). Therefore, we cannot just move out of `self`, so we might end up in situations
157//!   where we have to clone objects to be put into the final objects or we have to move out of the
158//!   builder and leave the builder in a state where calling `build` again would have a different
159//!   behavior, which, again, is unintuitive.
160//!
161//! * Combining the two approaches above, e.g. by implementing methods `xyz` and `with_xyz`, where
162//!   `xyz` takes `&mut self` and `with_xyz` takes `self`. This combines the advantages of both
163//!   methods, but it makes defining the builder even more verbose and also requires at least one
164//!   of the two methods for each field to have a longer name.
165//!
166//! A problem shared amongst all the approaches above is that having conditionals or loops around
167//! calls to the builder break method chaining.
168//!
169//! The idea of this crate comes from the observation that the main reason builders are usually
170//! designed as fluid interfaces is that we want to express the pattern "here is an object and I
171//! want to call these methods on it" without explicitly defining the variable or referencing it
172//! everytime. Therefore, we introduce a hypothetical language construct that does exactly that:
173//!
174//! ```ignore
175//! let thing = using builder @ SomeBuilder::new() {
176//!     x(...);
177//!     y(...);
178//!     if some_condition {
179//!         z(...);
180//!     }
181//!     if some_other_condition {
182//!         some_function(&mut builder);
183//!     }
184//!     build()
185//! };
186//! ```
187//!
188//! This hypothetical `using` expression takes an expression of any type (with an optional
189//! @-binding) and a block expression. Inside that block, every public method and every public
190//! field of that type is in the local scope of that block. With that, the example above would be
191//! equivalent to:
192//!
193//! ```ignore
194//! let thing = {
195//!     let mut builder = SomeBuilder::new();
196//!     builder.x(...);
197//!     builder.y(...);
198//!     if some_condition {
199//!         builder.z(...);
200//!     }
201//!     if some_other_condition {
202//!         some_function(&mut builder);
203//!     }
204//!     builder.build()
205//! };
206//! ```
207//!
208//! This is also known as [Method cascading](https://en.wikipedia.org/wiki/Method_cascading) and is
209//! an actual feature in some languages, notably Pascal and Visual Basic (initiated with the
210//! keyword `with`; we only chose `using` because the crate name was free ¯\\\_(ツ)\_/¯).
211//!
212//! The [`using`] macro emulates this behavior, with some restrictions due to the way macros are
213//! interpreted, e.g. in the context of macros, we do not know the type of the given expression and
214//! its public symbols, therefore we have to prefix method calls with a dot. Also, this way of
215//! accessing members does not work in all contexts; for details, see the documentation of
216//! [`using`].
217//!
218//! Writing builders with the [`using`] macro can be done by just defining a simple setter method
219//! for each field, making the code for builder very concise. If the to-be-constructed struct is
220//! simple enough, this could even make defining a builder obsolete. Also, the `build` method can
221//! now take both `self` or `&mut self` without breaking method chaining, which is usually a
222//! drawback of defining builders taking `&mut self`.
223
224#![cfg_attr(not(test), no_std)]
225
226/// A macro that provides method cascading for an object.
227///
228/// # Usage
229///
230/// ```plain
231/// using!(expression => { ... })
232///
233/// using!(identifier @ expression => { ... })
234/// ```
235///
236/// Binds `expression` to a mutable variable (called "target") that can be manipulated inside the
237/// block with expressions starting with a dot (called "target expressions"). The target variable
238/// can be explicitly named with an @-binding. If the block does not contain a trailing expression,
239/// the target is returned instead.
240///
241/// Target expression are a sequence of field accessess (e.g. `.x`) and method calls (e.g.
242/// `.push(10)`) and can only be used in blocks, let statements, bodies of if expressions, match
243/// expressions, and loops. They cannot be used in the conditional expressions and also not in
244/// compound expressions, e.g. `.last().unwrap() + 1` is not valid. For details see below.
245///
246/// Besides the target expressions, every statement and expression can be used inside the block,
247/// which also allows nesting [`using`] macros.
248///
249/// # Examples:
250///
251/// ```
252/// # use using::using;
253/// let hello_world = using!(Vec::new() => {
254///     .push("Hello");
255///     .push("World!");
256///     .join(", ")
257/// });
258/// assert_eq!(hello_world, "Hello, World!");
259///
260/// // Generated code:
261/// //
262/// // let hello_world = {
263/// //     let mut target = Vec::new();
264/// //     target.push("Hello");
265/// //     target.push("World!");
266/// //     target.join(", ")
267/// // };
268/// ```
269///
270/// More complicated example with `for`, `if`, and `let`:
271///
272/// ```
273/// # use using::using;
274/// let vec = using!(Vec::new() => {
275///     for i in 0..10 {
276///         if i % 2 == 0 {
277///             .push(i);
278///         }
279///     }
280///     let sum = .iter().sum();
281///     .push(sum);
282/// });
283/// assert_eq!(&vec[..], [ 0, 2, 4, 6, 8, 20 ]);
284/// ```
285///
286/// # Syntax:
287///
288/// This section explains the syntax in a BNF-like form to clarify the details and where target
289/// expressions can be used. The symbols `IDENTIFIER`, `Statement`, `Expression`,
290/// `BlockExpression`, `Pattern`, `GenericArgs`, `CallParams`, and `Type` are defined in [The Rust
291/// Reference](https://doc.rust-lang.org/stable/reference/). The syntax of the macro is defined by:
292///
293/// ```plain
294/// "using" "!" "(" Expression "=>" UsingBlock ")"
295///
296/// "using" "!" "(" IDENTIFIER "@" Expression "=>" UsingBlock ")"
297/// ```
298///
299/// A `UsingBlock` is an extension of Rusts `BlockExpression`: it is a block surrounded by curly
300/// braces, containing a sequence of `UsingStatement`s followed by an optional `UsingExpression`.
301///
302/// A `UsingStatement` is either a `Statement` or one of the following:
303///
304/// ```plain
305/// UsingExpression ";"
306///
307/// "let" IDENTIFIER ( ":" Type )? = UsingExpression ";"
308/// ```
309///
310/// A `UsingExpression` is either an `Expression` or one of the following:
311///
312/// ```plain
313/// UsingBlock
314///
315/// // This defines the "target expressions"
316/// ( "." IDENTIFIER | "." IDENTIFIER ( "::" GenericArgs )? "(" CallParams? ")" )+
317///
318/// "if" Expression UsingBlock ( "else" "if" Expression UsingBlock )* ( "else" UsingBlock )?
319///
320/// "match" Expression "{" ( Pattern ( "if" Expression )? => ( UsingBlock | UsingExpression "," ) )* "}"
321///
322/// "loop" UsingBlock
323///
324/// "while" Pattern "in" Expression UsingBlock
325///
326/// "for" Pattern "in" Expression UsingBlock
327/// ```
328#[macro_export]
329macro_rules! using {
330    ($target:expr => { $( $t:tt )* }) => {
331        {
332            #[allow(unused_mut)]
333            let mut target = $target;
334            $crate::using_impl!(target root empty { $($t)* })
335        }
336    };
337    ($id:ident @ $target:expr => { $( $t:tt )* }) => {
338        {
339            #[allow(unused_mut)]
340            let mut $id = $target;
341            $crate::using_impl!($id root empty { $($t)* })
342        }
343    };
344}
345
346#[doc(hidden)]
347#[macro_export]
348macro_rules! using_impl {
349    ($target:ident $scope:ident maybe_trailing_exp ($id:ident) { }) => {
350        $id
351    };
352
353    ($target:ident $scope:ident maybe_trailing_exp ($id:ident) { ; $($rest:tt)* }) => {
354        $crate::using_impl!($target $scope empty { $($rest)* })
355    };
356
357    ($target:ident $scope:ident maybe_trailing_exp ($id:ident) { $($rest:tt)* }) => {
358        $crate::using_impl!($target $scope empty { $($rest)* })
359    };
360
361
362
363    ($target:ident root empty { }) => {
364        $target
365    };
366
367    ($target:ident block empty { }) => {
368        #[allow(unreachable_code)]
369        ()
370    };
371
372    ($target:ident $scope:ident empty { ; $($rest:tt)* }) => {
373        {
374            ;
375            $crate::using_impl!($target $scope empty { $($rest)* })
376        }
377    };
378
379
380
381    ($target:ident $scope:ident empty { . $($rest:tt)* }) => {
382        $crate::using_impl!($target $scope in_exp ($target) { . $($rest)* })
383    };
384
385    ($target:ident $scope:ident in_exp ($exp:expr) { . $name:ident $( ::<$($ty:ty),* $(,)?> )? ( $($args:expr),* $(,)? ) $($rest:tt)* }) => {
386        $crate::using_impl!($target $scope in_exp ($exp.$name$(::<$($ty),*>)*($($args),*)) { $($rest)* })
387    };
388
389    ($target:ident $scope:ident in_exp ($exp:expr) { . $name:ident $($rest:tt)* }) => {
390        $crate::using_impl!($target $scope in_exp ($exp.$name) { $($rest)* })
391    };
392
393    ($target:ident $scope:ident in_exp ($exp:expr) { }) => {
394        $exp
395    };
396
397    ($target:ident $scope:ident in_exp ($exp:expr) { ; $($rest:tt)* }) => {
398        {
399            $exp;
400            $crate::using_impl!($target $scope empty { $($rest)* })
401        }
402    };
403
404    ($target:ident $scope:ident in_exp ($exp:expr) { . $name:ident = $value:expr; $($rest:tt)* }) => {
405        {
406            $exp.$name = $value;
407            $crate::using_impl!($target $scope empty { $($rest)* })
408        }
409    };
410
411
412
413    ($target:ident $scope:ident empty { { $($block:tt)* } }) => {
414        $crate::using_impl!($target block empty { $($block)* })
415    };
416
417    ($target:ident $scope:ident empty { { $($block:tt)* } $($rest:tt)* }) => {
418        {
419            $crate::using_impl!($target block empty { $($block)* });
420            $crate::using_impl!($target $scope empty { $($rest)* })
421        }
422    };
423
424
425
426    ($target:ident $scope:ident empty { let $($rest:tt)* }) => {
427        $crate::using_impl!($target $scope in_let () { $($rest)* })
428    };
429
430    ($target:ident $scope:ident in_let
431        ($($pattern:tt)*)
432        { = $($rest:tt)* }
433    ) => {
434        $crate::using_impl!($target $scope in_let_exp ($($pattern)*) (_) () { $($rest)* })
435    };
436
437    ($target:ident $scope:ident in_let
438        ($($pattern:tt)*)
439        { : $ty:ty = $($rest:tt)* }
440    ) => {
441        $crate::using_impl!($target $scope in_let_exp ($($pattern)*) ($ty) () { $($rest)* })
442    };
443
444    ($target:ident $scope:ident in_let
445        ($($pattern:tt)*)
446        { $t:tt $($rest:tt)* }
447    ) => {
448        $crate::using_impl!($target $scope in_let ($($pattern)* $t) { $($rest)* })
449    };
450
451    ($target:ident $scope:ident in_let_exp
452        ($pattern:pat)
453        ($ty:ty)
454        ($($exp:tt)*)
455        { ; $($rest:tt)* }
456    ) => {
457        {
458            let $pattern: $ty = $crate::using_impl!($target block empty { $($exp)* });
459            $crate::using_impl!($target $scope empty { $($rest)* })
460        }
461    };
462
463    ($target:ident $scope:ident in_let_exp
464        ($pattern:pat)
465        ($ty:ty)
466        ($($exp:tt)*)
467        { $t:tt $($rest:tt)* }
468    ) => {
469        $crate::using_impl!($target $scope in_let_exp ($pattern) ($ty) ($($exp)* $t) { $($rest)* })
470    };
471
472
473
474    ($target:ident $scope:ident empty { if $($rest:tt)* }) => {
475        $crate::using_impl!($target $scope in_if () () () { $($rest)* })
476    };
477
478    ($target:ident $scope:ident in_if
479        ($($if_curr:tt)*)
480        ()
481        ()
482        { { $($body:tt)* } $($rest:tt)* }
483    ) => {
484        $crate::using_impl!($target $scope in_if_next
485            ()
486            (($($if_curr)*) { $($body)* })
487            ()
488            { $($rest)* }
489        )
490    };
491
492    ($target:ident $scope:ident in_if
493        ($($if_curr:tt)*)
494        ($($if_first:tt)*)
495        ($($if_rest:tt)*)
496        { { $($body:tt)* } $($rest:tt)* }
497    ) => {
498        $crate::using_impl!($target $scope in_if_next
499            ()
500            ($($if_first)*)
501            ($($if_rest)* (($($if_curr)*) { $($body)* }))
502            { $($rest)* }
503        )
504    };
505
506    ($target:ident $scope:ident in_if
507        ($($if_curr:tt)*)
508        ($($if_first:tt)*)
509        ($($if_rest:tt)*)
510        { $t:tt $($rest:tt)* }
511    ) => {
512        $crate::using_impl!($target $scope in_if
513            ($($if_curr)* $t)
514            ($($if_first)*)
515            ($($if_rest)*)
516            { $($rest)* }
517        )
518    };
519
520    ($target:ident $scope:ident in_if_next
521        ()
522        ($($if_first:tt)*)
523        ($($if_rest:tt)*)
524        { else if $($rest:tt)* }
525    ) => {
526        $crate::using_impl!($target $scope in_if
527            ()
528            ($($if_first)*)
529            ($($if_rest)*)
530            { $($rest)* }
531        )
532    };
533
534    ($target:ident $scope:ident in_if_next
535        ()
536        (($($if_first_cond:tt)*) { $($if_first_body:tt)* })
537        ($( (($($if_rest_cond:tt)*) { $($if_rest_body:tt)* }) )*)
538        { else { $($body:tt)* } $($rest:tt)* }
539    ) => {
540        {
541            let _tmp = if $($if_first_cond)* {
542                $crate::using_impl!($target block empty { $($if_first_body)* })
543            } $( else if $($if_rest_cond)* {
544                $crate::using_impl!($target block empty { $($if_rest_body)* })
545            } )* else {
546                $crate::using_impl!($target block empty { $($body)* })
547            };
548            $crate::using_impl!($target $scope maybe_trailing_exp (_tmp) { $($rest)* })
549        }
550    };
551
552    ($target:ident $scope:ident in_if_next
553        ()
554        (($($if_first_cond:tt)*) { $($if_first_body:tt)* })
555        ($( (($($if_rest_cond:tt)*) { $($if_rest_body:tt)* }) )*)
556        { $($rest:tt)* }
557    ) => {
558        {
559            if $($if_first_cond)* {
560                $crate::using_impl!($target block empty { $($if_first_body)* })
561            } $( else if $($if_rest_cond)* {
562                $crate::using_impl!($target block empty { $($if_rest_body)* })
563            } )*
564            $crate::using_impl!($target $scope empty { $($rest)* })
565        }
566    };
567
568
569
570    ($target:ident $scope:ident empty { match $($rest:tt)* }) => {
571        $crate::using_impl!($target $scope in_match () { $($rest)* })
572    };
573
574    ($target:ident $scope:ident in_match
575        ($($match_cond:tt)*)
576        { { $($body:tt)* } $($rest:tt)* }
577    ) => {
578        $crate::using_impl!($target $scope in_match_body ($($match_cond)*) () { { $($body)* } $($rest)* })
579    };
580
581    ($target:ident $scope:ident in_match
582        ($($match_cond:tt)*)
583        { $t:tt $($rest:tt)* }
584    ) => {
585        $crate::using_impl!($target $scope in_match ($($match_cond)* $t) { $($rest)* })
586    };
587
588    ($target:ident $scope:ident in_match_body
589        ($($match_cond:tt)*)
590        ($($match_cases:tt)*)
591        { { $pattern:pat $( if $guard:expr )? => . $($body:tt)* } $($rest:tt)* }
592    ) => {
593        $crate::using_impl!($target $scope in_match_body_in_exp
594            ($($match_cond)*)
595            ($($match_cases)*)
596            (($pattern) $($guard)*)
597            (.)
598            { { $($body)* } $($rest)* }
599        )
600    };
601
602    ($target:ident $scope:ident in_match_body_in_exp
603        ($($match_cond:tt)*)
604        ($($match_cases:tt)*)
605        (($match_pattern:pat) $($match_guard:expr)?)
606        ($($match_exp:tt)*)
607        { { , $($body:tt)* } $($rest:tt)* }
608    ) => {
609        $crate::using_impl!($target $scope in_match_body
610            ($($match_cond)*)
611            ($($match_cases)* ($match_pattern $( if $match_guard )* => { $($match_exp)* }))
612            { { $($body)* } $($rest)* }
613        )
614    };
615
616    ($target:ident $scope:ident in_match_body_in_exp
617        ($($match_cond:tt)*)
618        ($($match_cases:tt)*)
619        (($match_pattern:pat) $($match_guard:expr)?)
620        ($($match_exp:tt)*)
621        { { } $($rest:tt)* }
622    ) => {
623        $crate::using_impl!($target $scope in_match_body
624            ($($match_cond)*)
625            ($($match_cases)* ($match_pattern $( if $match_guard )* => { $($match_exp)* }))
626            { { } $($rest)* }
627        )
628    };
629
630    ($target:ident $scope:ident in_match_body_in_exp
631        ($($match_cond:tt)*)
632        ($($match_cases:tt)*)
633        (($match_pattern:pat) $($match_guard:expr)?)
634        ($($match_exp:tt)*)
635        { { $t:tt $($body:tt)* } $($rest:tt)* }
636    ) => {
637        $crate::using_impl!($target $scope in_match_body_in_exp
638            ($($match_cond)*)
639            ($($match_cases)*)
640            (($match_pattern) $($match_guard)*)
641            ($($match_exp)* $t)
642            { { $($body)* } $($rest)* }
643        )
644    };
645
646    ($target:ident $scope:ident in_match_body
647        ($($match_cond:tt)*)
648        ($($match_cases:tt)*)
649        { { $pattern:pat $( if $guard:expr )? => { $($exp:tt)* }, $($body:tt)* } $($rest:tt)* }
650    ) => {
651        $crate::using_impl!($target $scope in_match_body
652            ($($match_cond)*)
653            ($($match_cases)* ($pattern $( if $guard )* => { $($exp)* }))
654            { { $($body)* } $($rest)* }
655        )
656    };
657
658    ($target:ident $scope:ident in_match_body
659        ($($match_cond:tt)*)
660        ($($match_cases:tt)*)
661        { { $pattern:pat $( if $guard:expr )? => { $($exp:tt)* } $($body:tt)* } $($rest:tt)* }
662    ) => {
663        $crate::using_impl!($target $scope in_match_body
664            ($($match_cond)*)
665            ($($match_cases)* ($pattern $( if $guard )* => { $($exp)* }))
666            { { $($body)* } $($rest)* }
667        )
668    };
669
670    ($target:ident $scope:ident in_match_body
671        ($($match_cond:tt)*)
672        ($($match_cases:tt)*)
673        { { $pattern:pat $( if $guard:expr )? => $exp:expr, $($body:tt)* } $($rest:tt)* }
674    ) => {
675        $crate::using_impl!($target $scope in_match_body
676            ($($match_cond)*)
677            ($($match_cases)* ($pattern $( if $guard )* => { $exp }))
678            { { $($body)* } $($rest)* }
679        )
680    };
681
682    ($target:ident $scope:ident in_match_body
683        ($($match_cond:tt)*)
684        ($($match_cases:tt)*)
685        { { $pattern:pat $( if $guard:expr )? => $exp:expr } $($rest:tt)* }
686    ) => {
687        $crate::using_impl!($target $scope in_match_body
688            ($($match_cond)*)
689            ($($match_cases)* ($pattern $( if $guard )* => { $exp }))
690            { { } $($rest)* }
691        )
692    };
693
694    ($target:ident $scope:ident in_match_body
695        ($($match_cond:tt)*)
696        ($( ($pattern:pat $( if $guard:expr )? => { $($exp:tt)* }) )*)
697        { { } $($rest:tt)* }
698    ) => {
699        {
700            let _tmp = match $($match_cond)* {
701                $( $pattern $( if $guard )* => { $crate::using_impl!($target block empty { $($exp)* }) }, )*
702            };
703            $crate::using_impl!($target $scope maybe_trailing_exp (_tmp) { $($rest)* })
704        }
705    };
706
707
708
709    ($target:ident $scope:ident empty { loop { $($body:tt)* } $($rest:tt)* }) => {
710        {
711            let _tmp = loop {
712                $crate::using_impl!($target block empty { $($body)* })
713            };
714            $crate::using_impl!($target $scope maybe_trailing_exp (_tmp) { $($rest)* })
715        }
716    };
717
718
719
720    ($target:ident $scope:ident empty { while $($rest:tt)* }) => {
721        $crate::using_impl!($target $scope in_while () { $($rest)* })
722    };
723
724    ($target:ident $scope:ident in_while
725        ($($while_cond:tt)*)
726        { { $($body:tt)* } $($rest:tt)* }
727    ) => {
728        {
729            while $($while_cond)* {
730                $crate::using_impl!($target block empty { $($body)* })
731            }
732            $crate::using_impl!($target $scope empty { $($rest)* })
733        }
734    };
735
736    ($target:ident $scope:ident in_while
737        ($($while_cond:tt)*)
738        { $t:tt $($rest:tt)* }
739    ) => {
740        $crate::using_impl!($target $scope in_while ($($while_cond)* $t) { $($rest)* })
741    };
742
743
744
745    ($target:ident $scope:ident empty { for $for_pattern:pat in $($rest:tt)* }) => {
746        $crate::using_impl!($target $scope in_for ($for_pattern) () { $($rest)* })
747    };
748
749    ($target:ident $scope:ident in_for
750        ($for_pattern:pat)
751        ($($for_exp:tt)*)
752        { { $($body:tt)* } $($rest:tt)* }
753    ) => {
754        {
755            for $for_pattern in $($for_exp)* {
756                $crate::using_impl!($target block empty { $($body)* })
757            }
758            $crate::using_impl!($target $scope empty { $($rest)* })
759        }
760    };
761
762    ($target:ident $scope:ident in_for
763        ($for_pattern:pat)
764        ($($for_exp:tt)*)
765        { $t:tt $($rest:tt)* }
766    ) => {
767        $crate::using_impl!($target $scope in_for ($for_pattern) ($($for_exp)* $t) { $($rest)* })
768    };
769
770
771
772    ($target:ident $scope:ident empty { $st:stmt; $($rest:tt)* }) => {
773        {
774            $st
775            $crate::using_impl!($target $scope empty { $($rest)* })
776        }
777    };
778
779    ($target:ident $scope:ident empty { $exp:expr }) => {
780        $exp
781    };
782}
783
784#[cfg(test)]
785mod tests {
786    use crate::using;
787
788    #[test]
789    fn simple() {
790        let vec = using!(Vec::new() => {
791            .push(1);
792            .push(2);
793            .push(3);
794            .push(4);
795            .push(5);
796        });
797        assert_eq!(vec.iter().sum::<i32>(), 15);
798    }
799
800    #[test]
801    fn simple_expr() {
802        let sum = using!(Vec::new() => {
803            .push(1);
804            .push(2);
805            .push(3);
806            .push(4);
807            .push(5);
808            .iter().sum::<i32>()
809        });
810        assert_eq!(sum, 15);
811    }
812
813    #[test]
814    fn block_expr() {
815        let sum: i32 = using!(Vec::new() => {
816            .push(1);
817            {
818                .push(2);
819                .push(3);
820            }
821            .push(4);
822            {
823                .push(5);
824                .iter().sum()
825            }
826        });
827        assert_eq!(sum, 15);
828    }
829
830    #[test]
831    fn if_expr() {
832        for i in 0..3 {
833            let res = using!(Vec::new() => {
834                if let 0 = i {
835                    .push(0);
836                } else if i == 1 {
837                    .push(1);
838                } else {
839                    .push(2);
840                }
841                .pop().unwrap()
842            });
843            assert_eq!(res, i);
844        }
845    }
846
847    #[test]
848    fn match_expr() {
849        for i in 0..9 {
850            let res = using!(vec @ Vec::new() => {
851                match i {
852                    0 => .push(0),
853                    1 => vec.push(1),
854                    2 => { .push(2) }
855                    3 => { .push(3) },
856                    4 if true => .push(4),
857                    5 if true => vec.push(5),
858                    6 if true => { .push(6) }
859                    7 if true => { .push(7) },
860                    _ => { .push(8) }
861                }
862                .pop().unwrap()
863            });
864            assert_eq!(res, i);
865        }
866    }
867
868    #[test]
869    fn loop_expr() {
870        let sum: i32 = using!(Vec::new() => {
871            let mut i = 1;
872            loop {
873                if i > 5 {
874                    break;
875                }
876                .push(i);
877                i += 1;
878            }
879            .iter().sum()
880        });
881        assert_eq!(sum, 15);
882    }
883
884    #[test]
885    fn while_loop() {
886        let sum: i32 = using!(Vec::new() => {
887            let mut i = 1;
888            while i <= 5 {
889                .push(i);
890                i += 1;
891            }
892            .iter().sum()
893        });
894        assert_eq!(sum, 15);
895    }
896
897    #[test]
898    fn while_let() {
899        let sum: i32 = using!(Vec::new() => {
900            let mut i = 1;
901            while let Some(_) = (i <= 5).then_some(i) {
902                .push(i);
903                i += 1;
904            }
905            .iter().sum()
906        });
907        assert_eq!(sum, 15);
908    }
909
910    #[test]
911    fn for_loop() {
912        let sum: i32 = using!(Vec::new() => {
913            for i in 1..=5 {
914                .push(i);
915            }
916            .iter().sum()
917        });
918        assert_eq!(sum, 15);
919    }
920
921    #[test]
922    fn if_in_for() {
923        let sum: i32 = using!(Vec::new() => {
924            for i in 1..=10 {
925                if i % 2 == 0 {
926                    .push(i);
927                }
928            }
929            .iter().sum()
930        });
931        assert_eq!(sum, 30);
932    }
933
934    #[test]
935    fn let_exp() {
936        let sum: i32 = using!(Vec::new() => {
937            .push(1);
938            .push(2);
939            .push(3);
940            let sum = .iter().sum();
941            .push(sum);
942            let res = { .pop().unwrap() };
943            2 * res
944        });
945        assert_eq!(sum, 12);
946    }
947
948    #[test]
949    fn let_complex() {
950        let res = using!(Vec::new() => {
951            .push(2);
952            .push(3);
953            .push(5);
954            let a = loop { let x = .last().unwrap(); break *x };
955            let b = if a < 10 { .first().is_some() } else { .is_empty() };
956            let c = match b { true => .len(), false => 0 };
957            (a, b, c)
958        });
959        assert_eq!(res, (5, true, 3));
960    }
961
962    #[test]
963    fn nested_using() {
964        let sum: i32 = using!(Vec::new() => {
965            .push(1);
966            .push(2);
967            .push(3);
968            .push(4);
969            .push(5);
970            .push(using!(Vec::new() => {
971                .push(2);
972                .push(3);
973                .iter().product()
974            }));
975            .iter().sum()
976        });
977        assert_eq!(sum, 21);
978    }
979}