stry_common/utils/fenn/
capture.rs

1/// A macro that allows you to clone, reference or copy variables captured by a
2/// closure.
3///
4/// # Clone (default)
5///
6/// Without any other modifiers the default action taken for arguments is to
7/// clone them.
8///
9/// ## Syntax
10///
11/// ```ignore
12/// capture!(var)                          // let var = var.clone();
13/// capture!(mut var)                      // let mut var = var.clone();
14/// capture!(var1 => var2)                 // let var2 = var1.clone();
15/// capture!(var1 => mut var2)             // let mut var2 = var1.clone();
16/// ```
17///
18/// # Copy
19///
20/// Copying is possible my adding a `*` to the appropriate argument.
21///
22/// ## Syntax
23///
24/// ```ignore
25/// capture!(*var)                         // let var = *var;
26/// capture!(mut *var)                     // let mut var = *var;
27/// capture!(*var1 => var2)                // let var2 = *var1;
28/// capture!(*var1 => mut var2)            // let mut var2 = *var1;
29/// ```
30///
31/// # References
32///
33/// You can reference a argument by adding the `ref` keyword to it.
34///
35/// ## Syntax
36///
37/// ```ignore
38/// capture!(ref var)                      // let var = &var;
39/// capture!(mut ref var)                  // let mut var = &var;
40/// capture!(ref mut var)                  // let var = &mut var;
41/// capture!(mut ref mut var)              // let mut var = &mut var;
42/// capture!(ref var1 => var2)             // let var2 = &var1;
43/// capture!(ref var1 => mut var2)         // let mut var2 = &var1;
44/// capture!(ref mut var1 => var2)         // let var2 = &mut var1;
45/// capture!(ref mut var1 => mut var2)     // let mut var2 = &mut var1;
46/// ```
47///
48/// ## Note
49///
50/// References' syntax complexity increases along with you use case.
51/// The order between `ref mut` and `mut ref` matters!
52///
53/// # Examples
54///
55/// ```rust
56/// use std::sync::{Arc, Mutex, atomic::{AtomicBool, Ordering}};
57///
58/// fn test() {
59///     let arc_atomic = Arc::new(AtomicBool::new(false));
60///     let arc_mutex = Arc::new(Mutex::new(Ordering::AcqRel));
61///
62///     run({
63///         fenn::capture!(arc_atomic, arc_mutex => mutex);
64///
65///         move || {
66///             let lock = mutex.lock().unwrap();
67///
68///             arc_atomic.store(true, *lock);
69///         }
70///     });
71/// }
72///
73/// fn run(f: impl FnOnce() -> ()) {
74///     f();
75/// }
76/// ```
77// TODO: figure out a way to pass closures as an argument so there doesn't need to be a block
78#[macro_export]
79macro_rules! capture {
80    //#region [ rgba(27, 133, 184, 0.1) ] copy arguments
81    // rename (with tokens)
82    // c!(*var1 => mut var2)            let mut var2 = *var1;
83    (@data, *$from:expr => mut $to:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
84        let mut $to $(: $ty )? = *$from;
85
86        $crate::capture!(@data, $( $tt )* )
87    };
88    // c!(*var1 => var2)                let var2 = *var1;
89    (@data, *$from:expr => $to:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
90        let $to $(: $ty )? = *$from;
91
92        $crate::capture!(@data, $( $tt )* )
93    };
94
95    // rename (without tokens)
96    // c!(*var1 => mut var2)            let mut var2 = *var1;
97    (@data, *$from:expr => mut $to:ident $(: $ty:ty)? ) => {
98        let mut $to $(: $ty )? = *$from;
99    };
100    // c!(*var1 => var2)                let var2 = *var1;
101    (@data, *$from:expr => $to:ident $(: $ty:ty)? ) => {
102        let $to $(: $ty )? = *$from;
103    };
104
105    // shadow (with tokens)
106    // c!(mut *var)                     let mut var = *var;
107    (@data, mut *$v:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
108        let mut $v $(: $ty )? = *$v;
109
110        $crate::capture!(@data, $( $tt )* )
111    };
112    // c!(*var)                         let var = *var;
113    (@data, *$v:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
114        let $v $(: $ty )? = *$v;
115
116        $crate::capture!(@data, $( $tt )* )
117    };
118
119    // shadow (without tokens)
120    // c!(mut *var)                     let mut var = *var;
121    (@data, mut *$v:ident $(: $ty:ty)? ) => {
122        let mut $v $(: $ty )? = *$v;
123    };
124    // c!(*var)                         let var = *var;
125    (@data, *$v:ident $(: $ty:ty)? ) => {
126        let $v $(: $ty )? = *$v;
127    };
128    //#endregion copy arguments
129
130
131    //#region [ rgba(174, 90, 65, 0.1) ] reference arguments
132    // rename (with tokens)
133    // c!(ref mut var1 => mut var2)     let mut var2 = &mut var1;
134    (@data, ref mut $from:expr => mut $to:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
135        let mut $to $(: $ty )? = &mut $from;
136
137        $crate::capture!(@data, $( $tt )* )
138    };
139    // c!(ref mut var1 => var2)         let var2 = &mut var1;
140    (@data, ref mut $from:expr => $to:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
141        let $to $(: $ty )? = &mut $from;
142
143        $crate::capture!(@data, $( $tt )* )
144    };
145    // c!(ref var1 => mut var2)         let mut var2 = &var1;
146    (@data, ref $from:expr => mut $to:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
147        let mut $to $(: $ty )? = &$from;
148
149        $crate::capture!(@data, $( $tt )* )
150    };
151    // c!(ref var1 => var2)             let var2 = &var1;
152    (@data, ref $from:expr => $to:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
153        let $to $(: $ty )? = &$from;
154
155        $crate::capture!(@data, $( $tt )* )
156    };
157
158    // rename (without tokens)
159    // c!(ref mut var1 => mut var2)     let mut var2 = &mut var1;
160    (@data, ref mut $from:expr => mut $to:ident $(: $ty:ty)? ) => {
161        let mut $to $(: $ty )? = &mut $from;
162    };
163    // c!(ref mut var1 => var2)         let var2 = &mut var1;
164    (@data, ref mut $from:expr => $to:ident $(: $ty:ty)? ) => {
165        let $to $(: $ty )? = &mut $from;
166    };
167    // c!(ref var1 => mut var2)         let mut var2 = &var1;
168    (@data, ref $from:expr => mut $to:ident $(: $ty:ty)? ) => {
169        let mut $to $(: $ty )? = &$from;
170    };
171    // c!(ref var1 => var2)             let var2 = &var1;
172    (@data, ref $from:expr => $to:ident $(: $ty:ty)? ) => {
173        let $to $(: $ty )? = &$from;
174    };
175
176    // shadow (with tokens)
177    // c!(mut ref mut var)              let mut var = &mut var;
178    (@data, mut ref mut $v:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
179        let mut $v $(: $ty )? = &mut $v;
180
181        $crate::capture!(@data, $( $tt )* )
182    };
183    // c!(mut ref var)                  let mut var = &var;
184    (@data, mut ref $v:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
185        let mut $v $(: $ty )? = &$v;
186
187        $crate::capture!(@data, $( $tt )* )
188    };
189    // c!(ref mut var)                  let var = &mut var;
190    (@data, ref mut $v:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
191        let mut $v $(: $ty )? = &$v;
192
193        $crate::capture!(@data, $( $tt )* )
194    };
195    // c!(ref var)                      let var = &var;
196    (@data, ref $v:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
197        let $v $(: $ty )? = &$v;
198
199        $crate::capture!(@data, $( $tt )* )
200    };
201
202    // shadow (without tokens)
203    // c!(mut ref mut var)              let mut var = &mut var;
204    (@data, mut ref mut $v:ident $(: $ty:ty)? ) => {
205        let mut $v $(: $ty )? = &mut $v;
206    };
207    // c!(mut ref var)                  let mut var = &var;
208    (@data, mut ref $v:ident $(: $ty:ty)? ) => {
209        let mut $v $(: $ty )? = &$v;
210    };
211    // c!(ref mut var)                  let var = &mut var;
212    (@data, ref mut $v:ident $(: $ty:ty)? ) => {
213        let $v $(: $ty )? = &mut $v;
214    };
215    // c!(ref var)                      let var = &var;
216    (@data, ref $v:ident $(: $ty:ty)? ) => {
217        let $v $(: $ty )? = &$v;
218    };
219    //#endregion reference arguments
220
221
222    //#region [ rgba(85, 158, 131, 0.1) ] clone arguments
223    // rename (with tokens)
224    // c!(var1 => mut var2)             let mut var2 = var1.clone();
225    (@data, $from:expr => mut $to:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
226        let mut $to $(: $ty )? = $from.clone();
227
228        $crate::capture!(@data, $( $tt )* )
229    };
230    // c!(var1 => var2)                 let var2 = var1.clone();
231    (@data, $from:expr => $to:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
232        let $to $(: $ty )? = $from.clone();
233
234        $crate::capture!(@data, $( $tt )* )
235    };
236
237    // rename (without tokens)
238    // c!(var1 => mut var2)             let mut var2 = var1.clone();
239    (@data, $from:expr => mut $to:ident $(: $ty:ty)? ) => {
240        let mut $to $(: $ty )? = $from.clone();
241    };
242    // c!(var1 => var2)                 let var2 = var1.clone();
243    (@data, $from:expr => $to:ident $(: $ty:ty)? ) => {
244        let $to $(: $ty )? = $from.clone();
245    };
246
247    // shadow (with tokens)
248    // c!(mut var)                      let mut var = var.clone();
249    (@data, mut $v:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
250        let mut $v $(: $ty )? = $v.clone();
251
252        $crate::capture!(@data, $( $tt )* )
253    };
254    // c!(var)                          let var = var.clone();
255    (@data, $v:ident $(: $ty:ty)?, $( $tt:tt )* ) => {
256        let $v $(: $ty )? = $v.clone();
257
258        $crate::capture!(@data, $( $tt )* )
259    };
260
261    // shadow (without tokens)
262    // c!(mut var)                      let mut var = var.clone();
263    (@data, mut $v:ident $(: $ty:ty)? ) => {
264        let mut $v $(: $ty )? = $v.clone();
265    };
266    // c!(var)                          let var = var.clone();
267    (@data, $v:ident $(: $ty:ty)? ) => {
268        let $v $(: $ty )? = $v.clone();
269    };
270    //#endregion clone arguments
271
272    // No tokens
273    (@data,) => {};
274
275
276    ( $( $var_tt:tt )* ) => {
277        $crate::capture! { @data, $( $var_tt )* }
278    };
279}