Skip to main content

qubit_function/macros/
closure_once_trait.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # Closure Once Trait Implementation Macro
10//!
11//! This module provides the `impl_closure_once_trait!` macro for implementing
12//! common conversion methods for closure-based once traits.
13//!
14//! ## Overview
15//!
16//! The macro generates standard conversion methods (`into_box`, `into_fn`) for
17//! traits that are implemented by closures with once semantics. It
18//! automatically infers all necessary information from the function signature
19//! and trait name.
20//!
21//! ## Generated Methods
22//!
23//! - `into_box()`: Converts the closure into a boxed wrapper type
24//! - `into_fn()`: Returns the closure as a generic `FnOnce` implementation
25//! - Core method: Direct delegation to the underlying closure
26//!
27//! ## Usage
28//!
29//! The macro is typically used in trait definitions to provide consistent
30//! conversion methods across different once trait implementations.
31//!
32//! ## Author
33//!
34//! Haixing Hu
35
36/// Implement common conversion methods for closure once traits
37///
38/// This macro generates standard conversion methods for all once traits
39/// that are implemented by closures. It automatically infers everything from
40/// the function signature and trait name.
41///
42/// # Parameters
43///
44/// * `$trait_name<$(generics),*>` - Full trait name with generics (e.g., `ConsumerOnce<T>`, `BiFunctionOnce<T, U, R>`)
45/// * `$method_name` - Core method name (e.g., `accept`, `apply`)
46/// * `$box_type` - Box wrapper type (e.g., `BoxConsumerOnce`, `BoxBiFunctionOnce`)
47/// * `$fn_trait` - Function signature (e.g., `FnOnce(value: &T)`, `FnOnce(first: &T, second: &U) -> R`)
48///
49/// # Generated implementation
50///
51/// ```text
52/// impl<F> ConsumerOnce<i32> for F
53/// where
54///     F: FnOnce(&i32),
55/// {
56///     fn accept(self, value: &i32);
57///     fn into_box(self) -> BoxConsumerOnce<i32>;
58///     fn into_fn(self) -> impl FnOnce(&i32);
59/// }
60/// ```
61///
62/// # Examples
63///
64/// ```text
65/// impl_closure_once_trait!(
66///     ConsumerOnce<i32>,
67///     accept,
68///     BoxConsumerOnce,
69///     FnOnce(value: &i32)
70/// );
71///
72/// impl_closure_once_trait!(
73///     FunctionOnce<i32, i32>,
74///     apply,
75///     BoxFunctionOnce,
76///     FnOnce(input: &i32) -> i32
77/// );
78///
79/// impl_closure_once_trait!(
80///     BiFunctionOnce<i32, i32, i32>,
81///     apply,
82///     BoxBiFunctionOnce,
83///     FnOnce(first: &i32, second: &i32) -> i32
84/// );
85/// ```
86///
87/// # Author
88///
89/// Haixing Hu
90macro_rules! impl_closure_once_trait {
91  // ==================== Internal Implementation ====================
92
93  // Core implementation: Generate complete trait implementation
94  (
95      @impl
96      $trait_name:ident < $($generics:ident),* >,
97      $method_name:ident,
98      $box_type:ident,
99      ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
100  ) => {
101      impl<F, $($generics),*> $trait_name<$($generics),*> for F
102      where
103          F: FnOnce($($arg_ty),*) $(-> $ret)?,
104      {
105          // Core method: Direct closure call
106          #[inline]
107          fn $method_name(self, $($arg : $arg_ty),*) $(-> $ret)? {
108              self($($arg),*)
109          }
110
111          // into_box: Convert to Box type
112          #[inline]
113          fn into_box(self) -> $box_type<$($generics),*>
114          where
115              Self: Sized + 'static,
116          {
117              $box_type::new(self)
118          }
119
120          // into_fn: Convert to closure (always return self directly since F is already FnOnce)
121          #[inline]
122          fn into_fn(self) -> impl FnOnce($($arg_ty),*) $(-> $ret)?
123          where
124              Self: Sized + 'static,
125          {
126              // F is already FnOnce with the correct signature, return directly (zero cost)
127              self
128          }
129      }
130  };
131
132  // ==================== Public Interface ====================
133
134  // No return value version
135  (
136      $trait_name:ident < $($generics:ident),* >,
137      $method_name:ident,
138      $box_type:ident,
139      FnOnce($($arg:ident : $arg_ty:ty),*)
140  ) => {
141      impl_closure_once_trait!(
142          @impl
143          $trait_name<$($generics),*>,
144          $method_name,
145          $box_type,
146          ($($arg : $arg_ty),*)
147      );
148  };
149
150  // With return value version
151  (
152      $trait_name:ident < $($generics:ident),* >,
153      $method_name:ident,
154      $box_type:ident,
155      FnOnce($($arg:ident : $arg_ty:ty),*) -> $ret:ty
156  ) => {
157      impl_closure_once_trait!(
158          @impl
159          $trait_name<$($generics),*>,
160          $method_name,
161          $box_type,
162          ($($arg : $arg_ty),*) -> $ret
163      );
164  };
165}
166
167pub(crate) use impl_closure_once_trait;