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        fn into_box(self) -> $box_type<$($generics),*>
118        where
119            $($generics: 'static),*
120        {
121            $box_type::new_with_optional_name(
122                impl_arc_conversions!(@make_closure $call_mode, self.function,
123                                      $($arg),*),
124                self.name
125            )
126        }
127    };
128
129    // Helper: Generate a single conversion method (consuming self) - to Rc
130    (
131        @method_into_rc
132        $arc_type:ident < $($generics:ident),* >,
133        $rc_type:ident,
134        $call_mode:ident,
135        ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
136    ) => {
137        fn into_rc(self) -> $rc_type<$($generics),*>
138        where
139            $($generics: 'static),*
140        {
141            $rc_type::new_with_optional_name(
142                impl_arc_conversions!(@make_closure $call_mode, self.function,
143                                      $($arg),*),
144                self.name
145            )
146        }
147    };
148
149    // Helper: Generate a single conversion method (consuming self) - to Once
150    (
151        @method_into_once
152        $arc_type:ident < $($generics:ident),* >,
153        $once_type:ident,
154        $call_mode:ident,
155        ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
156    ) => {
157        fn into_once(self) -> $once_type<$($generics),*>
158        where
159            $($generics: 'static),*
160        {
161            $once_type::new_with_optional_name(
162                impl_arc_conversions!(@make_closure $call_mode, self.function,
163                                      $($arg),*),
164                self.name
165            )
166        }
167    };
168
169    // Helper: Generate a single conversion method (borrowing &self) - to Box
170    (
171        @method_to_box
172        $arc_type:ident < $($generics:ident),* >,
173        $box_type:ident,
174        $call_mode:ident,
175        ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
176    ) => {
177        fn to_box(&self) -> $box_type<$($generics),*>
178        where
179            $($generics: 'static),*
180        {
181            let self_fn = self.function.clone();
182            let self_name = self.name.clone();
183            $box_type::new_with_optional_name(
184                impl_arc_conversions!(@make_closure $call_mode, self_fn,
185                                      $($arg),*),
186                self_name
187            )
188        }
189    };
190
191    // Helper: Generate a single conversion method (borrowing &self) - to Rc
192    (
193        @method_to_rc
194        $arc_type:ident < $($generics:ident),* >,
195        $rc_type:ident,
196        $call_mode:ident,
197        ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
198    ) => {
199        fn to_rc(&self) -> $rc_type<$($generics),*>
200        where
201            $($generics: 'static),*
202        {
203            let self_fn = self.function.clone();
204            let self_name = self.name.clone();
205            $rc_type::new_with_optional_name(
206                impl_arc_conversions!(@make_closure $call_mode, self_fn,
207                                      $($arg),*),
208                self_name
209            )
210        }
211    };
212
213    // Helper: Generate a single conversion method (borrowing &self) - to Once
214    (
215        @method_to_once
216        $arc_type:ident < $($generics:ident),* >,
217        $once_type:ident,
218        $call_mode:ident,
219        ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
220    ) => {
221        fn to_once(&self) -> $once_type<$($generics),*>
222        where
223            $($generics: 'static),*
224        {
225            let self_fn = self.function.clone();
226            let self_name = self.name.clone();
227            $once_type::new_with_optional_name(
228                impl_arc_conversions!(@make_closure $call_mode, self_fn,
229                                      $($arg),*),
230                self_name
231            )
232        }
233    };
234
235    // Helper: Generate into_fn method (consuming self, no return type, direct)
236    (
237        @fn_method_into
238        direct,
239        ($($arg:ident : $arg_ty:ty),*)
240    ) => {
241        fn into_fn(self) -> impl Fn($($arg_ty),*)
242        {
243            move |$($arg),*| (self.function)($($arg),*)
244        }
245    };
246
247    // Helper: Generate into_fn method (consuming self, with return type, direct)
248    (
249        @fn_method_into
250        direct,
251        ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
252    ) => {
253        fn into_fn(self) -> impl Fn($($arg_ty),*) -> $ret
254        {
255            move |$($arg),*| (self.function)($($arg),*)
256        }
257    };
258
259    // Helper: Generate into_fn method (consuming self, no return type, lock_unwrap)
260    (
261        @fn_method_into
262        lock_unwrap,
263        ($($arg:ident : $arg_ty:ty),*)
264    ) => {
265        fn into_fn(self) -> impl FnMut($($arg_ty),*)
266        {
267            move |$($arg),*| (self.function.lock())($($arg),*)
268        }
269    };
270
271    // Helper: Generate into_fn method (consuming self, with return type,
272    // lock_unwrap)
273    (
274        @fn_method_into
275        lock_unwrap,
276        ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
277    ) => {
278        fn into_fn(self) -> impl FnMut($($arg_ty),*) -> $ret
279        {
280            move |$($arg),*| (self.function.lock())($($arg),*)
281        }
282    };
283
284    // Helper: Generate to_fn method (borrowing &self, no return type, direct)
285    (
286        @fn_method_to
287        direct,
288        ($($arg:ident : $arg_ty:ty),*)
289    ) => {
290        fn to_fn(&self) -> impl Fn($($arg_ty),*)
291        {
292            let self_fn = self.function.clone();
293            move |$($arg),*| (self_fn)($($arg),*)
294        }
295    };
296
297    // Helper: Generate to_fn method (borrowing &self, with return type, direct)
298    (
299        @fn_method_to
300        direct,
301        ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
302    ) => {
303        fn to_fn(&self) -> impl Fn($($arg_ty),*) -> $ret
304        {
305            let self_fn = self.function.clone();
306            move |$($arg),*| (self_fn)($($arg),*)
307        }
308    };
309
310    // Helper: Generate to_fn method (borrowing &self, no return type, lock_unwrap)
311    (
312        @fn_method_to
313        lock_unwrap,
314        ($($arg:ident : $arg_ty:ty),*)
315    ) => {
316        fn to_fn(&self) -> impl FnMut($($arg_ty),*)
317        {
318            let self_fn = self.function.clone();
319            move |$($arg),*| (self_fn.lock())($($arg),*)
320        }
321    };
322
323    // Helper: Generate to_fn method (borrowing &self, with return type,
324    // lock_unwrap)
325    (
326        @fn_method_to
327        lock_unwrap,
328        ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
329    ) => {
330        fn to_fn(&self) -> impl FnMut($($arg_ty),*) -> $ret
331        {
332            let self_fn = self.function.clone();
333            move |$($arg),*| (self_fn.lock())($($arg),*)
334        }
335    };
336
337    // Helper: Make closure based on call mode
338    (@make_closure direct, $fn_call:expr, $($arg:ident),*) => {
339        move |$($arg),*| ($fn_call)($($arg),*)
340    };
341    (@make_closure lock_unwrap, $fn_call:expr, $($arg:ident),*) => {
342        move |$($arg),*| ($fn_call.lock())($($arg),*)
343    };
344
345    // ==================== Main Implementation ====================
346
347    // Internal implementation: Generate all methods
348    (
349        @impl
350        $arc_type:ident < $($generics:ident),* >,
351        $box_type:ident,
352        $rc_type:ident,
353        $once_type:ident,
354        $call_mode:ident,
355        ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
356    ) => {
357        // into_box: consumes self, returns Box
358        impl_arc_conversions!(
359            @method_into_box
360            $arc_type<$($generics),*>, $box_type,
361            $call_mode,
362            ($($arg : $arg_ty),*) $(-> $ret)?
363        );
364
365        // into_rc: consumes self, returns Rc
366        impl_arc_conversions!(
367            @method_into_rc
368            $arc_type<$($generics),*>, $rc_type,
369            $call_mode,
370            ($($arg : $arg_ty),*) $(-> $ret)?
371        );
372
373        // into_arc: consumes self, returns self (zero-cost)
374        fn into_arc(self) -> $arc_type<$($generics),*>
375        where
376            $($generics: 'static),*
377        {
378            self
379        }
380
381        // into_fn: consumes self, returns impl Fn/FnMut
382        impl_arc_conversions!(
383            @fn_method_into
384            $call_mode,
385            ($($arg : $arg_ty),*) $(-> $ret)?
386        );
387
388        // into_once: consumes self, returns Once
389        impl_arc_conversions!(
390            @method_into_once
391            $arc_type<$($generics),*>, $once_type,
392            $call_mode,
393            ($($arg : $arg_ty),*) $(-> $ret)?
394        );
395
396        // to_box: borrows self, clones and returns Box
397        impl_arc_conversions!(
398            @method_to_box
399            $arc_type<$($generics),*>, $box_type,
400            $call_mode,
401            ($($arg : $arg_ty),*) $(-> $ret)?
402        );
403
404        // to_rc: borrows self, clones and returns Rc
405        impl_arc_conversions!(
406            @method_to_rc
407            $arc_type<$($generics),*>, $rc_type,
408            $call_mode,
409            ($($arg : $arg_ty),*) $(-> $ret)?
410        );
411
412        // to_arc: borrows self, returns clone (cheap Arc clone)
413        fn to_arc(&self) -> $arc_type<$($generics),*>
414        where
415            $($generics: 'static),*
416        {
417            self.clone()
418        }
419
420        // to_fn: borrows self, clones and returns impl Fn/FnMut
421        impl_arc_conversions!(
422            @fn_method_to
423            $call_mode,
424            ($($arg : $arg_ty),*) $(-> $ret)?
425        );
426
427        // to_once: borrows self, clones and returns Once
428        impl_arc_conversions!(
429            @method_to_once
430            $arc_type<$($generics),*>, $once_type,
431            $call_mode,
432            ($($arg : $arg_ty),*) $(-> $ret)?
433        );
434    };
435
436    // Internal implementation: Generate methods without once type
437    (
438        @impl_no_once
439        $arc_type:ident < $($generics:ident),* >,
440        $box_type:ident,
441        $rc_type:ident,
442        $call_mode:ident,
443        ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
444    ) => {
445        // into_box: consumes self, returns Box
446        impl_arc_conversions!(
447            @method_into_box
448            $arc_type<$($generics),*>, $box_type,
449            $call_mode,
450            ($($arg : $arg_ty),*) $(-> $ret)?
451        );
452
453        // into_rc: consumes self, returns Rc
454        impl_arc_conversions!(
455            @method_into_rc
456            $arc_type<$($generics),*>, $rc_type,
457            $call_mode,
458            ($($arg : $arg_ty),*) $(-> $ret)?
459        );
460
461        // into_arc: consumes self, returns self (zero-cost)
462        fn into_arc(self) -> $arc_type<$($generics),*>
463        where
464            $($generics: 'static),*
465        {
466            self
467        }
468
469        // into_fn: consumes self, returns impl Fn/FnMut
470        impl_arc_conversions!(
471            @fn_method_into
472            $call_mode,
473            ($($arg : $arg_ty),*) $(-> $ret)?
474        );
475
476        // to_box: borrows self, clones and returns Box
477        impl_arc_conversions!(
478            @method_to_box
479            $arc_type<$($generics),*>, $box_type,
480            $call_mode,
481            ($($arg : $arg_ty),*) $(-> $ret)?
482        );
483
484        // to_rc: borrows self, clones and returns Rc
485        impl_arc_conversions!(
486            @method_to_rc
487            $arc_type<$($generics),*>, $rc_type,
488            $call_mode,
489            ($($arg : $arg_ty),*) $(-> $ret)?
490        );
491
492        // to_arc: borrows self, returns clone (cheap Arc clone)
493        fn to_arc(&self) -> $arc_type<$($generics),*>
494        where
495            $($generics: 'static),*
496        {
497            self.clone()
498        }
499
500        // to_fn: borrows self, clones and returns impl Fn/FnMut
501        impl_arc_conversions!(
502            @fn_method_to
503            $call_mode,
504            ($($arg : $arg_ty),*) $(-> $ret)?
505        );
506    };
507
508    // ==================== Public Interface ====================
509
510    // Fn(...) → direct call mode (immutable, no interior mutability)
511    (
512        $arc_type:ident < $($generics:ident),* >,
513        $box_type:ident,
514        $rc_type:ident,
515        $once_type:ident,
516        Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
517    ) => {
518        impl_arc_conversions!(
519            @impl
520            $arc_type<$($generics),*>,
521            $box_type,
522            $rc_type,
523            $once_type,
524            direct,
525            ($($arg : $arg_ty),*) $(-> $ret)?
526        );
527    };
528
529    // FnMut(...) → lock_unwrap call mode (mutable, needs Mutex)
530    (
531        $arc_type:ident < $($generics:ident),* >,
532        $box_type:ident,
533        $rc_type:ident,
534        $once_type:ident,
535        FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
536    ) => {
537        impl_arc_conversions!(
538            @impl
539            $arc_type<$($generics),*>,
540            $box_type,
541            $rc_type,
542            $once_type,
543            lock_unwrap,
544            ($($arg : $arg_ty),*) $(-> $ret)?
545        );
546    };
547
548    // Fn(...) → direct call mode (immutable, no interior mutability) - no once type
549    (
550        $arc_type:ident < $($generics:ident),* >,
551        $box_type:ident,
552        $rc_type:ident,
553        Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
554    ) => {
555        impl_arc_conversions!(
556            @impl_no_once
557            $arc_type<$($generics),*>,
558            $box_type,
559            $rc_type,
560            direct,
561            ($($arg : $arg_ty),*) $(-> $ret)?
562        );
563    };
564
565    // FnMut(...) → lock_unwrap call mode (mutable, needs Mutex) - no once type
566    (
567        $arc_type:ident < $($generics:ident),* >,
568        $box_type:ident,
569        $rc_type:ident,
570        FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
571    ) => {
572        impl_arc_conversions!(
573            @impl_no_once
574            $arc_type<$($generics),*>,
575            $box_type,
576            $rc_type,
577            lock_unwrap,
578            ($($arg : $arg_ty),*) $(-> $ret)?
579        );
580    };
581}
582
583pub(crate) use impl_arc_conversions;