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