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 {
277 self
278 }
279
280 // into_fn: consumes self, returns impl Fn/FnMut
281 impl_rc_conversions!(
282 @fn_method_into
283 $call_mode,
284 ($($arg : $arg_ty),*) $(-> $ret)?
285 );
286
287 // to_box: borrows self, clones and returns Box
288 impl_rc_conversions!(
289 @method_to to_box,
290 $rc_type<$($generics),*>, $box_type,
291 $call_mode,
292 ($($arg : $arg_ty),*) $(-> $ret)?
293 );
294
295 // to_rc: borrows self, returns clone (cheap Rc clone)
296 #[inline]
297 fn to_rc(&self) -> $rc_type<$($generics),*>
298 {
299 self.clone()
300 }
301
302 // to_fn: borrows self, clones and returns impl Fn/FnMut
303 impl_rc_conversions!(
304 @fn_method_to
305 $call_mode,
306 ($($arg : $arg_ty),*) $(-> $ret)?
307 );
308 };
309
310 // Internal implementation: Generate all methods (with once type)
311 (
312 @impl
313 $rc_type:ident < $($generics:ident),* >,
314 $box_type:ident,
315 $once_type:ident,
316 $call_mode:ident,
317 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
318 ) => {
319 // Generate common methods
320 impl_rc_conversions!(
321 @impl_common
322 $rc_type<$($generics),*>,
323 $box_type,
324 $call_mode,
325 ($($arg : $arg_ty),*) $(-> $ret)?
326 );
327
328 // into_once: consumes self, returns Once
329 impl_rc_conversions!(
330 @method_into into_once,
331 $rc_type<$($generics),*>,
332 $once_type,
333 $call_mode,
334 ($($arg : $arg_ty),*) $(-> $ret)?
335 );
336
337 // to_once: borrows self, clones and returns Once
338 impl_rc_conversions!(
339 @method_to to_once,
340 $rc_type<$($generics),*>,
341 $once_type,
342 $call_mode,
343 ($($arg : $arg_ty),*) $(-> $ret)?
344 );
345 };
346
347 // Internal implementation: Generate methods without once type
348 (
349 @impl_no_once
350 $rc_type:ident < $($generics:ident),* >,
351 $box_type:ident,
352 $call_mode:ident,
353 ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
354 ) => {
355 // Generate common methods only
356 impl_rc_conversions!(
357 @impl_common
358 $rc_type<$($generics),*>,
359 $box_type,
360 $call_mode,
361 ($($arg : $arg_ty),*) $(-> $ret)?
362 );
363 };
364
365 // ==================== Public Interface ====================
366
367 // Fn(...) → direct call mode (immutable, no interior mutability) - no once type
368 (
369 $rc_type:ident < $($generics:ident),* >,
370 $box_type:ident,
371 Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
372 ) => {
373 impl_rc_conversions!(
374 @impl_no_once
375 $rc_type<$($generics),*>,
376 $box_type,
377 direct,
378 ($($arg : $arg_ty),*) $(-> $ret)?
379 );
380 };
381
382 // FnMut(...) → borrow_mut call mode (mutable, needs RefCell/Mutex) - no once type
383 (
384 $rc_type:ident < $($generics:ident),* >,
385 $box_type:ident,
386 FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
387 ) => {
388 impl_rc_conversions!(
389 @impl_no_once
390 $rc_type<$($generics),*>,
391 $box_type,
392 borrow_mut,
393 ($($arg : $arg_ty),*) $(-> $ret)?
394 );
395 };
396
397 // Fn(...) → direct call mode (immutable, no interior mutability) - with once type
398 (
399 $rc_type:ident < $($generics:ident),* >,
400 $box_type:ident,
401 $once_type:ident,
402 Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
403 ) => {
404 impl_rc_conversions!(
405 @impl
406 $rc_type<$($generics),*>,
407 $box_type,
408 $once_type,
409 direct,
410 ($($arg : $arg_ty),*) $(-> $ret)?
411 );
412 };
413
414 // FnMut(...) → borrow_mut call mode (mutable, needs RefCell/Mutex) - with once type
415 (
416 $rc_type:ident < $($generics:ident),* >,
417 $box_type:ident,
418 $once_type:ident,
419 FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
420 ) => {
421 impl_rc_conversions!(
422 @impl
423 $rc_type<$($generics),*>,
424 $box_type,
425 $once_type,
426 borrow_mut,
427 ($($arg : $arg_ty),*) $(-> $ret)?
428 );
429 };
430}
431
432pub(crate) use impl_rc_conversions;