qubit_function/macros/rc_conversions.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9
10//! # Rc Conversions Macro
11//!
12//! Generates common into_xxx() conversion methods for all Rc-based function
13//! wrappers.
14//!
15//! This macro generates the standard conversion methods (`into_box`, `into_rc`,
16//! `into_fn`, `into_once`) for all Rc-based function wrapper types using a
17//! single unified pattern.
18//!
19//! # Author
20//!
21//! Haixing Hu
22
23/// Public interface macro for Rc-based conversions.
24///
25/// This macro automatically infers everything from the function signature:
26/// - Number of parameters
27/// - Parameter types
28/// - Return type
29/// - Call mode (Fn → direct, FnMut → borrow_mut)
30///
31/// # Syntax
32///
33/// ```rust
34/// // 2-parameter version (no once type, for predicates and similar pure functions)
35/// // impl_rc_conversions!(
36/// // RcType<Generics>, // Rc wrapper type with all generic parameters
37/// // BoxType, // Corresponding Box wrapper type
38/// // Fn(args) [-> RetType] // Fn or FnMut signature (auto-infers everything!)
39/// // );
40///
41/// // 3-parameter version (with once type, for consumers, functions, etc.)
42/// // impl_rc_conversions!(
43/// // RcType<Generics>, // Rc wrapper type with all generic parameters
44/// // BoxType, // Corresponding Box wrapper type
45/// // OnceType, // Corresponding once wrapper type
46/// // Fn(args) [-> RetType] // Fn or FnMut signature (auto-infers everything!)
47/// // );
48/// ```
49///
50/// # Generated methods
51///
52/// * `into_box(self) -> BoxType` - Converts to Box-based wrapper
53/// * `into_rc(self) -> RcType` - Converts to Rc-based wrapper
54/// * `into_fn(self) -> impl FnTrait` - Converts to function pointer
55/// * `into_once(self) -> OnceType` - Converts to once wrapper
56/// * `to_box(&self) -> BoxType` - Converts to Box-based wrapper
57/// * `to_rc(&self) -> RcType` - Converts to Rc-based wrapper
58/// * `to_fn(&self) -> impl FnTrait` - Converts to function pointer
59/// * `to_once(&self) -> OnceType` - Converts to once wrapper
60///
61/// # Examples
62///
63/// ```rust
64/// // use qubit_function::{
65/// // RcPredicate, BoxPredicate, RcBiPredicate, BoxBiPredicate, RcConsumer, BoxConsumer, BoxConsumerOnce,
66/// // RcStatefulConsumer, BoxStatefulConsumer, RcBiConsumer, BoxBiConsumer, BoxBiConsumerOnce,
67/// // RcFunction, BoxFunction, BoxFunctionOnce, RcStatefulFunction, BoxStatefulFunction,
68/// // RcMutatingFunction, BoxMutatingFunction, BoxMutatingFunctionOnce,
69/// // };
70///
71/// // Predicate: Fn(&T) -> bool → direct call mode (no once type)
72/// // impl_rc_conversions!(RcPredicate<i32>, BoxPredicate, Fn(t: &i32) -> bool);
73///
74/// // BiPredicate: Fn(&T, &U) -> bool → direct call mode (no once type)
75/// // impl_rc_conversions!(RcBiPredicate<i32, i32>, BoxBiPredicate, Fn(t: &i32, u: &i32) -> bool);
76///
77/// // Consumer: Fn(&T) → direct call mode (with once type)
78/// // impl_rc_conversions!(RcConsumer<i32>, BoxConsumer, BoxConsumerOnce, Fn(t: &i32));
79///
80/// // StatefulConsumer: FnMut(&T) → borrow_mut call mode (with once type)
81/// // impl_rc_conversions!(RcStatefulConsumer<i32>, BoxStatefulConsumer, BoxConsumerOnce, FnMut(t: &i32));
82///
83/// // BiConsumer: Fn(&T, &U) → direct call mode (with once type)
84/// // impl_rc_conversions!(RcBiConsumer<i32, i32>, BoxBiConsumer, BoxBiConsumerOnce, Fn(t: &i32, u: &i32));
85///
86/// // Function: Fn(&T) -> R → direct call mode (with once type)
87/// // impl_rc_conversions!(RcFunction<i32, i32>, BoxFunction, BoxFunctionOnce, Fn(t: &i32) -> i32);
88///
89/// // StatefulFunction: FnMut(&T) -> R → borrow_mut call mode (with once type)
90/// // impl_rc_conversions!(RcStatefulFunction<i32, i32>, BoxStatefulFunction, BoxFunctionOnce, FnMut(t: &i32) -> i32);
91///
92/// // MutatingFunction: Fn(&mut T) -> R → direct call mode (with once type)
93/// // impl_rc_conversions!(RcMutatingFunction<i32, i32>, BoxMutatingFunction, BoxMutatingFunctionOnce, Fn(input: &mut i32) -> i32);
94/// ```
95///
96/// # Author
97///
98/// Haixing Hu
99macro_rules! impl_rc_conversions {
100 // ==================== Core Macro: Generate Single Method ====================
101
102 // Helper: Generate a single conversion method (consuming self)
103 (
104 @method_into
105 $method_name:ident, // Method name: into_box, into_once
106 $rc_type:ident < $($generics:ident),* >, // Rc type with generics
107 $target_type:ident, // Target type: BoxType or OnceType
108 $call_mode:ident, // direct or borrow_mut
109 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)? // Function signature
110 ) => {
111 #[inline]
112 fn $method_name(self) -> $target_type<$($generics),*>
113 where
114 Self: 'static,
115 {
116 $target_type::new_with_optional_name(
117 impl_rc_conversions!(@make_closure $call_mode, self.function, $($arg),*),
118 self.name
119 )
120 }
121 };
122
123 // Helper: Generate a single conversion method (borrowing &self)
124 (
125 @method_to
126 $method_name:ident, // Method name: to_box, to_once
127 $rc_type:ident < $($generics:ident),* >, // Rc type with generics
128 $target_type:ident, // Target type: BoxType or OnceType
129 $call_mode:ident, // direct or borrow_mut
130 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)? // Function signature
131 ) => {
132 #[inline]
133 fn $method_name(&self) -> $target_type<$($generics),*>
134 where
135 Self: 'static,
136 {
137 let self_fn = self.function.clone();
138 let self_name = self.name.clone();
139 $target_type::new_with_optional_name(
140 impl_rc_conversions!(@make_closure $call_mode, self_fn, $($arg),*),
141 self_name
142 )
143 }
144 };
145
146 // Helper: Generate into_fn method (consuming self, no return type, direct)
147 (
148 @fn_method_into
149 direct,
150 ($($arg:ident : $arg_ty:ty),*)
151 ) => {
152 #[inline]
153 fn into_fn(self) -> impl Fn($($arg_ty),*)
154 {
155 move |$($arg),*| (self.function)($($arg),*)
156 }
157 };
158
159 // Helper: Generate into_fn method (consuming self, with return type, direct)
160 (
161 @fn_method_into
162 direct,
163 ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
164 ) => {
165 #[inline]
166 fn into_fn(self) -> impl Fn($($arg_ty),*) -> $ret
167 {
168 move |$($arg),*| (self.function)($($arg),*)
169 }
170 };
171
172 // Helper: Generate into_fn method (consuming self, no return type, borrow_mut)
173 (
174 @fn_method_into
175 borrow_mut,
176 ($($arg:ident : $arg_ty:ty),*)
177 ) => {
178 #[inline]
179 fn into_fn(self) -> impl FnMut($($arg_ty),*)
180 {
181 move |$($arg),*| (self.function.borrow_mut())($($arg),*)
182 }
183 };
184
185 // Helper: Generate into_fn method (consuming self, with return type, borrow_mut)
186 (
187 @fn_method_into
188 borrow_mut,
189 ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
190 ) => {
191 #[inline]
192 fn into_fn(self) -> impl FnMut($($arg_ty),*) -> $ret
193 {
194 move |$($arg),*| (self.function.borrow_mut())($($arg),*)
195 }
196 };
197
198 // Helper: Generate to_fn method (borrowing &self, no return type, direct)
199 (
200 @fn_method_to
201 direct,
202 ($($arg:ident : $arg_ty:ty),*)
203 ) => {
204 #[inline]
205 fn to_fn(&self) -> impl Fn($($arg_ty),*)
206 {
207 let self_fn = self.function.clone();
208 move |$($arg),*| (self_fn)($($arg),*)
209 }
210 };
211
212 // Helper: Generate to_fn method (borrowing &self, with return type, direct)
213 (
214 @fn_method_to
215 direct,
216 ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
217 ) => {
218 #[inline]
219 fn to_fn(&self) -> impl Fn($($arg_ty),*) -> $ret
220 {
221 let self_fn = self.function.clone();
222 move |$($arg),*| (self_fn)($($arg),*)
223 }
224 };
225
226 // Helper: Generate to_fn method (borrowing &self, no return type, borrow_mut)
227 (
228 @fn_method_to
229 borrow_mut,
230 ($($arg:ident : $arg_ty:ty),*)
231 ) => {
232 #[inline]
233 fn to_fn(&self) -> impl FnMut($($arg_ty),*)
234 {
235 let self_fn = self.function.clone();
236 move |$($arg),*| (self_fn.borrow_mut())($($arg),*)
237 }
238 };
239
240 // Helper: Generate to_fn method (borrowing &self, with return type, borrow_mut)
241 (
242 @fn_method_to
243 borrow_mut,
244 ($($arg:ident : $arg_ty:ty),*) -> $ret:ty
245 ) => {
246 #[inline]
247 fn to_fn(&self) -> impl FnMut($($arg_ty),*) -> $ret
248 {
249 let self_fn = self.function.clone();
250 move |$($arg),*| (self_fn.borrow_mut())($($arg),*)
251 }
252 };
253
254 // Helper: Make closure based on call mode
255 (@make_closure direct, $fn_call:expr, $($arg:ident),*) => {
256 move |$($arg),*| ($fn_call)($($arg),*)
257 };
258 (@make_closure borrow_mut, $fn_call:expr, $($arg:ident),*) => {
259 move |$($arg),*| ($fn_call.borrow_mut())($($arg),*)
260 };
261
262 // ==================== Main Implementation ====================
263
264 // Internal implementation: Generate common methods (shared by both variants)
265 (
266 @impl_common
267 $rc_type:ident < $($generics:ident),* >,
268 $box_type:ident,
269 $call_mode:ident,
270 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
271 ) => {
272 // into_box: consumes self, returns Box
273 impl_rc_conversions!(
274 @method_into into_box,
275 $rc_type<$($generics),*>, $box_type,
276 $call_mode,
277 ($($arg : $arg_ty),*) $(-> $ret)?
278 );
279
280 // into_rc: consumes self, returns self (zero-cost)
281 #[inline]
282 fn into_rc(self) -> $rc_type<$($generics),*>
283 {
284 self
285 }
286
287 // into_fn: consumes self, returns impl Fn/FnMut
288 impl_rc_conversions!(
289 @fn_method_into
290 $call_mode,
291 ($($arg : $arg_ty),*) $(-> $ret)?
292 );
293
294 // to_box: borrows self, clones and returns Box
295 impl_rc_conversions!(
296 @method_to to_box,
297 $rc_type<$($generics),*>, $box_type,
298 $call_mode,
299 ($($arg : $arg_ty),*) $(-> $ret)?
300 );
301
302 // to_rc: borrows self, returns clone (cheap Rc clone)
303 #[inline]
304 fn to_rc(&self) -> $rc_type<$($generics),*>
305 {
306 self.clone()
307 }
308
309 // to_fn: borrows self, clones and returns impl Fn/FnMut
310 impl_rc_conversions!(
311 @fn_method_to
312 $call_mode,
313 ($($arg : $arg_ty),*) $(-> $ret)?
314 );
315 };
316
317 // Internal implementation: Generate all methods (with once type)
318 (
319 @impl
320 $rc_type:ident < $($generics:ident),* >,
321 $box_type:ident,
322 $once_type:ident,
323 $call_mode:ident,
324 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
325 ) => {
326 // Generate common methods
327 impl_rc_conversions!(
328 @impl_common
329 $rc_type<$($generics),*>,
330 $box_type,
331 $call_mode,
332 ($($arg : $arg_ty),*) $(-> $ret)?
333 );
334
335 // into_once: consumes self, returns Once
336 impl_rc_conversions!(
337 @method_into into_once,
338 $rc_type<$($generics),*>,
339 $once_type,
340 $call_mode,
341 ($($arg : $arg_ty),*) $(-> $ret)?
342 );
343
344 // to_once: borrows self, clones and returns Once
345 impl_rc_conversions!(
346 @method_to to_once,
347 $rc_type<$($generics),*>,
348 $once_type,
349 $call_mode,
350 ($($arg : $arg_ty),*) $(-> $ret)?
351 );
352 };
353
354 // Internal implementation: Generate methods without once type
355 (
356 @impl_no_once
357 $rc_type:ident < $($generics:ident),* >,
358 $box_type:ident,
359 $call_mode:ident,
360 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
361 ) => {
362 // Generate common methods only
363 impl_rc_conversions!(
364 @impl_common
365 $rc_type<$($generics),*>,
366 $box_type,
367 $call_mode,
368 ($($arg : $arg_ty),*) $(-> $ret)?
369 );
370 };
371
372 // ==================== Public Interface ====================
373
374 // Fn(...) → direct call mode (immutable, no interior mutability) - no once type
375 (
376 $rc_type:ident < $($generics:ident),* >,
377 $box_type:ident,
378 Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
379 ) => {
380 impl_rc_conversions!(
381 @impl_no_once
382 $rc_type<$($generics),*>,
383 $box_type,
384 direct,
385 ($($arg : $arg_ty),*) $(-> $ret)?
386 );
387 };
388
389 // FnMut(...) → borrow_mut call mode (mutable, needs RefCell/Mutex) - no once type
390 (
391 $rc_type:ident < $($generics:ident),* >,
392 $box_type:ident,
393 FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
394 ) => {
395 impl_rc_conversions!(
396 @impl_no_once
397 $rc_type<$($generics),*>,
398 $box_type,
399 borrow_mut,
400 ($($arg : $arg_ty),*) $(-> $ret)?
401 );
402 };
403
404 // Fn(...) → direct call mode (immutable, no interior mutability) - with once type
405 (
406 $rc_type:ident < $($generics:ident),* >,
407 $box_type:ident,
408 $once_type:ident,
409 Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
410 ) => {
411 impl_rc_conversions!(
412 @impl
413 $rc_type<$($generics),*>,
414 $box_type,
415 $once_type,
416 direct,
417 ($($arg : $arg_ty),*) $(-> $ret)?
418 );
419 };
420
421 // FnMut(...) → borrow_mut call mode (mutable, needs RefCell/Mutex) - with once type
422 (
423 $rc_type:ident < $($generics:ident),* >,
424 $box_type:ident,
425 $once_type:ident,
426 FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
427 ) => {
428 impl_rc_conversions!(
429 @impl
430 $rc_type<$($generics),*>,
431 $box_type,
432 $once_type,
433 borrow_mut,
434 ($($arg : $arg_ty),*) $(-> $ret)?
435 );
436 };
437}
438
439pub(crate) use impl_rc_conversions;