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}