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        {
391            self
392        }
393
394        // into_fn: consumes self, returns impl Fn/FnMut
395        impl_arc_conversions!(
396            @fn_method_into
397            $call_mode,
398            ($($arg : $arg_ty),*) $(-> $ret)?
399        );
400
401        // into_once: consumes self, returns Once
402        impl_arc_conversions!(
403            @method_into_once
404            $arc_type<$($generics),*>, $once_type,
405            $call_mode,
406            ($($arg : $arg_ty),*) $(-> $ret)?
407        );
408
409        // to_box: borrows self, clones and returns Box
410        impl_arc_conversions!(
411            @method_to_box
412            $arc_type<$($generics),*>, $box_type,
413            $call_mode,
414            ($($arg : $arg_ty),*) $(-> $ret)?
415        );
416
417        // to_rc: borrows self, clones and returns Rc
418        impl_arc_conversions!(
419            @method_to_rc
420            $arc_type<$($generics),*>, $rc_type,
421            $call_mode,
422            ($($arg : $arg_ty),*) $(-> $ret)?
423        );
424
425        // to_arc: borrows self, returns clone (cheap Arc clone)
426        #[inline]
427        fn to_arc(&self) -> $arc_type<$($generics),*>
428        {
429            self.clone()
430        }
431
432        // to_fn: borrows self, clones and returns impl Fn/FnMut
433        impl_arc_conversions!(
434            @fn_method_to
435            $call_mode,
436            ($($arg : $arg_ty),*) $(-> $ret)?
437        );
438
439        // to_once: borrows self, clones and returns Once
440        impl_arc_conversions!(
441            @method_to_once
442            $arc_type<$($generics),*>, $once_type,
443            $call_mode,
444            ($($arg : $arg_ty),*) $(-> $ret)?
445        );
446    };
447
448    // Internal implementation: Generate methods without once type
449    (
450        @impl_no_once
451        $arc_type:ident < $($generics:ident),* >,
452        $box_type:ident,
453        $rc_type:ident,
454        $call_mode:ident,
455        ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
456    ) => {
457        // into_box: consumes self, returns Box
458        impl_arc_conversions!(
459            @method_into_box
460            $arc_type<$($generics),*>, $box_type,
461            $call_mode,
462            ($($arg : $arg_ty),*) $(-> $ret)?
463        );
464
465        // into_rc: consumes self, returns Rc
466        impl_arc_conversions!(
467            @method_into_rc
468            $arc_type<$($generics),*>, $rc_type,
469            $call_mode,
470            ($($arg : $arg_ty),*) $(-> $ret)?
471        );
472
473        // into_arc: consumes self, returns self (zero-cost)
474        #[inline]
475        fn into_arc(self) -> $arc_type<$($generics),*>
476        {
477            self
478        }
479
480        // into_fn: consumes self, returns impl Fn/FnMut
481        impl_arc_conversions!(
482            @fn_method_into
483            $call_mode,
484            ($($arg : $arg_ty),*) $(-> $ret)?
485        );
486
487        // to_box: borrows self, clones and returns Box
488        impl_arc_conversions!(
489            @method_to_box
490            $arc_type<$($generics),*>, $box_type,
491            $call_mode,
492            ($($arg : $arg_ty),*) $(-> $ret)?
493        );
494
495        // to_rc: borrows self, clones and returns Rc
496        impl_arc_conversions!(
497            @method_to_rc
498            $arc_type<$($generics),*>, $rc_type,
499            $call_mode,
500            ($($arg : $arg_ty),*) $(-> $ret)?
501        );
502
503        // to_arc: borrows self, returns clone (cheap Arc clone)
504        #[inline]
505        fn to_arc(&self) -> $arc_type<$($generics),*>
506        {
507            self.clone()
508        }
509
510        // to_fn: borrows self, clones and returns impl Fn/FnMut
511        impl_arc_conversions!(
512            @fn_method_to
513            $call_mode,
514            ($($arg : $arg_ty),*) $(-> $ret)?
515        );
516    };
517
518    // ==================== Public Interface ====================
519
520    // Fn(...) → direct call mode (immutable, no interior mutability)
521    (
522        $arc_type:ident < $($generics:ident),* >,
523        $box_type:ident,
524        $rc_type:ident,
525        $once_type:ident,
526        Fn($($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            direct,
535            ($($arg : $arg_ty),*) $(-> $ret)?
536        );
537    };
538
539    // FnMut(...) → lock_unwrap call mode (mutable, needs Mutex)
540    (
541        $arc_type:ident < $($generics:ident),* >,
542        $box_type:ident,
543        $rc_type:ident,
544        $once_type:ident,
545        FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
546    ) => {
547        impl_arc_conversions!(
548            @impl
549            $arc_type<$($generics),*>,
550            $box_type,
551            $rc_type,
552            $once_type,
553            lock_unwrap,
554            ($($arg : $arg_ty),*) $(-> $ret)?
555        );
556    };
557
558    // Fn(...) → direct call mode (immutable, no interior mutability) - no once type
559    (
560        $arc_type:ident < $($generics:ident),* >,
561        $box_type:ident,
562        $rc_type:ident,
563        Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
564    ) => {
565        impl_arc_conversions!(
566            @impl_no_once
567            $arc_type<$($generics),*>,
568            $box_type,
569            $rc_type,
570            direct,
571            ($($arg : $arg_ty),*) $(-> $ret)?
572        );
573    };
574
575    // FnMut(...) → lock_unwrap call mode (mutable, needs Mutex) - no once type
576    (
577        $arc_type:ident < $($generics:ident),* >,
578        $box_type:ident,
579        $rc_type:ident,
580        FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
581    ) => {
582        impl_arc_conversions!(
583            @impl_no_once
584            $arc_type<$($generics),*>,
585            $box_type,
586            $rc_type,
587            lock_unwrap,
588            ($($arg : $arg_ty),*) $(-> $ret)?
589        );
590    };
591}
592
593pub(crate) use impl_arc_conversions;