prism3_function/macros/arc_conversions.rs
1////////////////////////////////////////////////////////////////////////////////
2//
3/*
4 * Copyright (c) 2025.
5 * 3-Prism Co. Ltd.
6 *
7 * All rights reserved.
8 *
9 */
10
11////////////////////////////////////////////////////////////////////////////////
12
13//! # Arc Conversions Macro
14//!
15//! Generates common into_xxx() conversion methods for all Arc-based function
16//! wrappers.
17//!
18//! This macro automatically infers everything from the function signature:
19//! - Number of parameters
20//! - Parameter types
21//! - Return type
22//! - Call mode (Fn → direct, FnMut → lock_unwrap)
23//!
24//! # Author
25//!
26//! Haixing Hu
27
28/// Public interface macro for Arc-based conversions.
29///
30/// This macro automatically infers everything from the function signature:
31/// - Number of parameters
32/// - Parameter types
33/// - Return type
34/// - Call mode (Fn → direct, FnMut → lock_unwrap)
35///
36/// # Syntax
37///
38/// ```ignore
39/// // 4-parameter version (with once type, for consumers, functions, etc.)
40/// impl_arc_conversions!(
41/// ArcType<Generics>, // Arc wrapper type with all generic params
42/// BoxType, // Corresponding Box wrapper type
43/// RcType, // Corresponding Rc wrapper type
44/// OnceType, // Corresponding once wrapper type
45/// Fn(args) [-> RetType] // Fn or FnMut signature (auto-infers everything!)
46/// );
47///
48/// // 3-parameter version (no once type, for predicates and similar pure functions)
49/// impl_arc_conversions!(
50/// ArcType<Generics>, // Arc wrapper type with all generic params
51/// BoxType, // Corresponding Box wrapper type
52/// RcType, // Corresponding Rc wrapper type
53/// Fn(args) [-> RetType] // Fn or FnMut signature (auto-infers everything!)
54/// );
55/// ```
56///
57/// # Examples
58///
59/// ```ignore
60/// // Predicate: Fn(&T) -> bool → direct call mode (no once type)
61/// impl_arc_conversions!(ArcPredicate<T>, BoxPredicate, RcPredicate,
62/// Fn(t: &T) -> bool);
63///
64/// // BiPredicate: Fn(&T, &U) -> bool → direct call mode (no once type)
65/// impl_arc_conversions!(ArcBiPredicate<T, U>, BoxBiPredicate, RcBiPredicate,
66/// Fn(t: &T, u: &U) -> bool);
67///
68/// // Consumer: Fn(&T) → direct call mode (with once type)
69/// impl_arc_conversions!(ArcConsumer<T>, BoxConsumer, RcConsumer,
70/// BoxConsumerOnce, Fn(t: &T));
71///
72/// // StatefulConsumer: FnMut(&T) → lock_unwrap call mode (with once type)
73/// impl_arc_conversions!(ArcStatefulConsumer<T>, BoxStatefulConsumer,
74/// RcStatefulConsumer, BoxConsumerOnce, FnMut(t: &T));
75///
76/// // BiConsumer: Fn(&T, &U) → direct call mode (with once type)
77/// impl_arc_conversions!(ArcBiConsumer<T, U>, BoxBiConsumer, RcBiConsumer,
78/// BoxBiConsumerOnce, Fn(t: &T, u: &U));
79///
80/// // Function: Fn(&T) -> R → direct call mode (with once type)
81/// impl_arc_conversions!(ArcFunction<T, R>, BoxFunction, RcFunction,
82/// BoxFunctionOnce, Fn(t: &T) -> R);
83///
84/// // StatefulFunction: FnMut(&T) -> R → lock_unwrap call mode (with once type)
85/// impl_arc_conversions!(ArcStatefulFunction<T, R>, BoxStatefulFunction,
86/// RcStatefulFunction, BoxFunctionOnce, FnMut(t: &T) -> R);
87///
88/// // MutatingFunction: Fn(&mut T) -> R → direct call mode (with once type)
89/// impl_arc_conversions!(ArcMutatingFunction<T, R>, BoxMutatingFunction,
90/// RcMutatingFunction, BoxMutatingFunctionOnce,
91/// Fn(input: &mut T) -> R);
92/// ```
93///
94/// # Author
95///
96/// Haixing Hu
97macro_rules! impl_arc_conversions {
98 // ==================== Core Macro: Generate Single Method ====================
99
100 // Helper: Generate a single conversion method (consuming self) - to Box
101 (
102 @method_into_box
103 $arc_type:ident < $($generics:ident),* >,
104 $box_type:ident,
105 $call_mode:ident,
106 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
107 ) => {
108 fn into_box(self) -> $box_type<$($generics),*>
109 where
110 $($generics: 'static),*
111 {
112 $box_type::new_with_optional_name(
113 impl_arc_conversions!(@make_closure $call_mode, self.function,
114 $($arg),*),
115 self.name
116 )
117 }
118 };
119
120 // Helper: Generate a single conversion method (consuming self) - to Rc
121 (
122 @method_into_rc
123 $arc_type:ident < $($generics:ident),* >,
124 $rc_type:ident,
125 $call_mode:ident,
126 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
127 ) => {
128 fn into_rc(self) -> $rc_type<$($generics),*>
129 where
130 $($generics: 'static),*
131 {
132 $rc_type::new_with_optional_name(
133 impl_arc_conversions!(@make_closure $call_mode, self.function,
134 $($arg),*),
135 self.name
136 )
137 }
138 };
139
140 // Helper: Generate a single conversion method (consuming self) - to Once
141 (
142 @method_into_once
143 $arc_type:ident < $($generics:ident),* >,
144 $once_type:ident,
145 $call_mode:ident,
146 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
147 ) => {
148 fn into_once(self) -> $once_type<$($generics),*>
149 where
150 $($generics: 'static),*
151 {
152 $once_type::new_with_optional_name(
153 impl_arc_conversions!(@make_closure $call_mode, self.function,
154 $($arg),*),
155 self.name
156 )
157 }
158 };
159
160 // Helper: Generate a single conversion method (borrowing &self) - to Box
161 (
162 @method_to_box
163 $arc_type:ident < $($generics:ident),* >,
164 $box_type:ident,
165 $call_mode:ident,
166 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
167 ) => {
168 fn to_box(&self) -> $box_type<$($generics),*>
169 where
170 $($generics: 'static),*
171 {
172 let self_fn = self.function.clone();
173 let self_name = self.name.clone();
174 $box_type::new_with_optional_name(
175 impl_arc_conversions!(@make_closure $call_mode, self_fn,
176 $($arg),*),
177 self_name
178 )
179 }
180 };
181
182 // Helper: Generate a single conversion method (borrowing &self) - to Rc
183 (
184 @method_to_rc
185 $arc_type:ident < $($generics:ident),* >,
186 $rc_type:ident,
187 $call_mode:ident,
188 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
189 ) => {
190 fn to_rc(&self) -> $rc_type<$($generics),*>
191 where
192 $($generics: 'static),*
193 {
194 let self_fn = self.function.clone();
195 let self_name = self.name.clone();
196 $rc_type::new_with_optional_name(
197 impl_arc_conversions!(@make_closure $call_mode, self_fn,
198 $($arg),*),
199 self_name
200 )
201 }
202 };
203
204 // Helper: Generate a single conversion method (borrowing &self) - to Once
205 (
206 @method_to_once
207 $arc_type:ident < $($generics:ident),* >,
208 $once_type:ident,
209 $call_mode:ident,
210 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
211 ) => {
212 fn to_once(&self) -> $once_type<$($generics),*>
213 where
214 $($generics: 'static),*
215 {
216 let self_fn = self.function.clone();
217 let self_name = self.name.clone();
218 $once_type::new_with_optional_name(
219 impl_arc_conversions!(@make_closure $call_mode, self_fn,
220 $($arg),*),
221 self_name
222 )
223 }
224 };
225
226 // Helper: Generate into_fn method (consuming self, no return type, direct)
227 (
228 @fn_method_into
229 direct,
230 ($($arg:ident : $arg_ty:ty),*)
231 ) => {
232 fn into_fn(self) -> impl Fn($($arg_ty),*)
233 {
234 move |$($arg),*| (self.function)($($arg),*)
235 }
236 };
237
238 // Helper: Generate into_fn method (consuming self, with return type, direct)
239 (
240 @fn_method_into
241 direct,
242 ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
243 ) => {
244 fn into_fn(self) -> impl Fn($($arg_ty),*) -> $ret
245 {
246 move |$($arg),*| (self.function)($($arg),*)
247 }
248 };
249
250 // Helper: Generate into_fn method (consuming self, no return type, lock_unwrap)
251 (
252 @fn_method_into
253 lock_unwrap,
254 ($($arg:ident : $arg_ty:ty),*)
255 ) => {
256 fn into_fn(self) -> impl FnMut($($arg_ty),*)
257 {
258 move |$($arg),*| (self.function.lock())($($arg),*)
259 }
260 };
261
262 // Helper: Generate into_fn method (consuming self, with return type,
263 // lock_unwrap)
264 (
265 @fn_method_into
266 lock_unwrap,
267 ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
268 ) => {
269 fn into_fn(self) -> impl FnMut($($arg_ty),*) -> $ret
270 {
271 move |$($arg),*| (self.function.lock())($($arg),*)
272 }
273 };
274
275 // Helper: Generate to_fn method (borrowing &self, no return type, direct)
276 (
277 @fn_method_to
278 direct,
279 ($($arg:ident : $arg_ty:ty),*)
280 ) => {
281 fn to_fn(&self) -> impl Fn($($arg_ty),*)
282 {
283 let self_fn = self.function.clone();
284 move |$($arg),*| (self_fn)($($arg),*)
285 }
286 };
287
288 // Helper: Generate to_fn method (borrowing &self, with return type, direct)
289 (
290 @fn_method_to
291 direct,
292 ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
293 ) => {
294 fn to_fn(&self) -> impl Fn($($arg_ty),*) -> $ret
295 {
296 let self_fn = self.function.clone();
297 move |$($arg),*| (self_fn)($($arg),*)
298 }
299 };
300
301 // Helper: Generate to_fn method (borrowing &self, no return type, lock_unwrap)
302 (
303 @fn_method_to
304 lock_unwrap,
305 ($($arg:ident : $arg_ty:ty),*)
306 ) => {
307 fn to_fn(&self) -> impl FnMut($($arg_ty),*)
308 {
309 let self_fn = self.function.clone();
310 move |$($arg),*| (self_fn.lock())($($arg),*)
311 }
312 };
313
314 // Helper: Generate to_fn method (borrowing &self, with return type,
315 // lock_unwrap)
316 (
317 @fn_method_to
318 lock_unwrap,
319 ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
320 ) => {
321 fn to_fn(&self) -> impl FnMut($($arg_ty),*) -> $ret
322 {
323 let self_fn = self.function.clone();
324 move |$($arg),*| (self_fn.lock())($($arg),*)
325 }
326 };
327
328 // Helper: Make closure based on call mode
329 (@make_closure direct, $fn_call:expr, $($arg:ident),*) => {
330 move |$($arg),*| ($fn_call)($($arg),*)
331 };
332 (@make_closure lock_unwrap, $fn_call:expr, $($arg:ident),*) => {
333 move |$($arg),*| ($fn_call.lock())($($arg),*)
334 };
335
336 // ==================== Main Implementation ====================
337
338 // Internal implementation: Generate all methods
339 (
340 @impl
341 $arc_type:ident < $($generics:ident),* >,
342 $box_type:ident,
343 $rc_type:ident,
344 $once_type:ident,
345 $call_mode:ident,
346 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
347 ) => {
348 // into_box: consumes self, returns Box
349 impl_arc_conversions!(
350 @method_into_box
351 $arc_type<$($generics),*>, $box_type,
352 $call_mode,
353 ($($arg : $arg_ty),*) $(-> $ret)?
354 );
355
356 // into_rc: consumes self, returns Rc
357 impl_arc_conversions!(
358 @method_into_rc
359 $arc_type<$($generics),*>, $rc_type,
360 $call_mode,
361 ($($arg : $arg_ty),*) $(-> $ret)?
362 );
363
364 // into_arc: consumes self, returns self (zero-cost)
365 fn into_arc(self) -> $arc_type<$($generics),*>
366 where
367 $($generics: 'static),*
368 {
369 self
370 }
371
372 // into_fn: consumes self, returns impl Fn/FnMut
373 impl_arc_conversions!(
374 @fn_method_into
375 $call_mode,
376 ($($arg : $arg_ty),*) $(-> $ret)?
377 );
378
379 // into_once: consumes self, returns Once
380 impl_arc_conversions!(
381 @method_into_once
382 $arc_type<$($generics),*>, $once_type,
383 $call_mode,
384 ($($arg : $arg_ty),*) $(-> $ret)?
385 );
386
387 // to_box: borrows self, clones and returns Box
388 impl_arc_conversions!(
389 @method_to_box
390 $arc_type<$($generics),*>, $box_type,
391 $call_mode,
392 ($($arg : $arg_ty),*) $(-> $ret)?
393 );
394
395 // to_rc: borrows self, clones and returns Rc
396 impl_arc_conversions!(
397 @method_to_rc
398 $arc_type<$($generics),*>, $rc_type,
399 $call_mode,
400 ($($arg : $arg_ty),*) $(-> $ret)?
401 );
402
403 // to_arc: borrows self, returns clone (cheap Arc clone)
404 fn to_arc(&self) -> $arc_type<$($generics),*>
405 where
406 $($generics: 'static),*
407 {
408 self.clone()
409 }
410
411 // to_fn: borrows self, clones and returns impl Fn/FnMut
412 impl_arc_conversions!(
413 @fn_method_to
414 $call_mode,
415 ($($arg : $arg_ty),*) $(-> $ret)?
416 );
417
418 // to_once: borrows self, clones and returns Once
419 impl_arc_conversions!(
420 @method_to_once
421 $arc_type<$($generics),*>, $once_type,
422 $call_mode,
423 ($($arg : $arg_ty),*) $(-> $ret)?
424 );
425 };
426
427 // Internal implementation: Generate methods without once type
428 (
429 @impl_no_once
430 $arc_type:ident < $($generics:ident),* >,
431 $box_type:ident,
432 $rc_type:ident,
433 $call_mode:ident,
434 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
435 ) => {
436 // into_box: consumes self, returns Box
437 impl_arc_conversions!(
438 @method_into_box
439 $arc_type<$($generics),*>, $box_type,
440 $call_mode,
441 ($($arg : $arg_ty),*) $(-> $ret)?
442 );
443
444 // into_rc: consumes self, returns Rc
445 impl_arc_conversions!(
446 @method_into_rc
447 $arc_type<$($generics),*>, $rc_type,
448 $call_mode,
449 ($($arg : $arg_ty),*) $(-> $ret)?
450 );
451
452 // into_arc: consumes self, returns self (zero-cost)
453 fn into_arc(self) -> $arc_type<$($generics),*>
454 where
455 $($generics: 'static),*
456 {
457 self
458 }
459
460 // into_fn: consumes self, returns impl Fn/FnMut
461 impl_arc_conversions!(
462 @fn_method_into
463 $call_mode,
464 ($($arg : $arg_ty),*) $(-> $ret)?
465 );
466
467 // to_box: borrows self, clones and returns Box
468 impl_arc_conversions!(
469 @method_to_box
470 $arc_type<$($generics),*>, $box_type,
471 $call_mode,
472 ($($arg : $arg_ty),*) $(-> $ret)?
473 );
474
475 // to_rc: borrows self, clones and returns Rc
476 impl_arc_conversions!(
477 @method_to_rc
478 $arc_type<$($generics),*>, $rc_type,
479 $call_mode,
480 ($($arg : $arg_ty),*) $(-> $ret)?
481 );
482
483 // to_arc: borrows self, returns clone (cheap Arc clone)
484 fn to_arc(&self) -> $arc_type<$($generics),*>
485 where
486 $($generics: 'static),*
487 {
488 self.clone()
489 }
490
491 // to_fn: borrows self, clones and returns impl Fn/FnMut
492 impl_arc_conversions!(
493 @fn_method_to
494 $call_mode,
495 ($($arg : $arg_ty),*) $(-> $ret)?
496 );
497 };
498
499 // ==================== Public Interface ====================
500
501 // Fn(...) → direct call mode (immutable, no interior mutability)
502 (
503 $arc_type:ident < $($generics:ident),* >,
504 $box_type:ident,
505 $rc_type:ident,
506 $once_type:ident,
507 Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
508 ) => {
509 impl_arc_conversions!(
510 @impl
511 $arc_type<$($generics),*>,
512 $box_type,
513 $rc_type,
514 $once_type,
515 direct,
516 ($($arg : $arg_ty),*) $(-> $ret)?
517 );
518 };
519
520 // FnMut(...) → lock_unwrap call mode (mutable, needs Mutex)
521 (
522 $arc_type:ident < $($generics:ident),* >,
523 $box_type:ident,
524 $rc_type:ident,
525 $once_type:ident,
526 FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
527 ) => {
528 impl_arc_conversions!(
529 @impl
530 $arc_type<$($generics),*>,
531 $box_type,
532 $rc_type,
533 $once_type,
534 lock_unwrap,
535 ($($arg : $arg_ty),*) $(-> $ret)?
536 );
537 };
538
539 // Fn(...) → direct call mode (immutable, no interior mutability) - no once type
540 (
541 $arc_type:ident < $($generics:ident),* >,
542 $box_type:ident,
543 $rc_type:ident,
544 Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
545 ) => {
546 impl_arc_conversions!(
547 @impl_no_once
548 $arc_type<$($generics),*>,
549 $box_type,
550 $rc_type,
551 direct,
552 ($($arg : $arg_ty),*) $(-> $ret)?
553 );
554 };
555
556 // FnMut(...) → lock_unwrap call mode (mutable, needs Mutex) - no once type
557 (
558 $arc_type:ident < $($generics:ident),* >,
559 $box_type:ident,
560 $rc_type:ident,
561 FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
562 ) => {
563 impl_arc_conversions!(
564 @impl_no_once
565 $arc_type<$($generics),*>,
566 $box_type,
567 $rc_type,
568 lock_unwrap,
569 ($($arg : $arg_ty),*) $(-> $ret)?
570 );
571 };
572}
573
574pub(crate) use impl_arc_conversions;