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;