Skip to main content

qubit_function/macros/
arc_conversions.rs

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