Skip to main content

qubit_function/macros/
closure_trait.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9
10/// Implement trait for closures with automatic type inference
11///
12/// This macro generates blanket implementations for closures implementing
13/// various function traits (Consumer, Function, Predicate, etc.). It
14/// automatically infers everything from the function signature and trait name.
15///
16/// # Parameters
17///
18/// * `$trait_name<$(generics),*>` - Full trait name with generics (e.g., `Consumer<T>`, `Function<T, R>`)
19/// * `$method_name` - Core method name (e.g., `accept`, `apply`, `test`)
20/// * `$once_type` - Optional once wrapper type (e.g., `BoxConsumerOnce`)
21/// * `$fn_signature` - Function signature (e.g., `Fn(value: &T)`, `FnMut(input: &T) -> R`)
22///
23/// # Generated implementation
24///
25/// Generates a blanket implementation for all closures matching the signature,
26/// including:
27/// - Core method implementation
28/// - `into_box`, `into_rc`, `into_arc`, `into_fn` methods
29/// - `to_box`, `to_rc`, `to_arc`, `to_fn` methods
30/// - `into_once`, `to_once` methods (if once_type is provided)
31///
32/// # Examples
33///
34/// ```ignore
35/// // Consumer trait (with once conversion)
36/// impl_closure_trait!(
37///     Consumer<T>,
38///     accept,
39///     BoxConsumerOnce,
40///     Fn(value: &T)
41/// );
42///
43/// // Function trait
44/// impl_closure_trait!(
45///     Function<T, R>,
46///     apply,
47///     BoxFunctionOnce,
48///     Fn(input: &T) -> R
49/// );
50///
51/// // Predicate trait (no once conversion)
52/// impl_closure_trait!(
53///     Predicate<T>,
54///     test,
55///     Fn(value: &T) -> bool
56/// );
57///
58/// // StatefulConsumer trait
59/// impl_closure_trait!(
60///     StatefulConsumer<T>,
61///     accept,
62///     BoxConsumerOnce,
63///     FnMut(value: &T)
64/// );
65/// ```
66///
67/// # Author
68///
69/// Haixing Hu
70macro_rules! impl_closure_trait {
71  // ==================== 辅助宏:生成 into_once 方法 ====================
72
73  // Fn trait: into_once 方法
74  (@into_once_fn_method $once_type:ident, ($($generics:ident),*)) => {
75      #[inline]
76      fn into_once(self) -> $once_type<$($generics),*>
77      where
78          Self: Sized + 'static,
79          $($generics: 'static,)*
80      {
81          $once_type::new(self)
82      }
83  };
84
85  // FnMut trait: into_once 方法
86  (@into_once_fnmut_method $once_type:ident, ($($generics:ident),*), ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?) => {
87      #[inline]
88      fn into_once(mut self) -> $once_type<$($generics),*>
89      where
90          Self: Sized + 'static,
91          $($generics: 'static,)*
92      {
93          $once_type::new(move |$($arg: $arg_ty),*| self($($arg),*))
94      }
95  };
96
97  // ==================== 辅助宏:生成 to_once 方法 ====================
98
99  // Fn trait: to_once 方法
100  (@to_once_fn_method $once_type:ident, ($($generics:ident),*)) => {
101      #[inline]
102      fn to_once(&self) -> $once_type<$($generics),*>
103      where
104          Self: Clone + Sized + 'static,
105          $($generics: 'static,)*
106      {
107          $once_type::new(self.clone())
108      }
109  };
110
111  // FnMut trait: to_once 方法
112  (@to_once_fnmut_method $once_type:ident, ($($generics:ident),*), ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?) => {
113      #[inline]
114      fn to_once(&self) -> $once_type<$($generics),*>
115      where
116          Self: Clone + Sized + 'static,
117          $($generics: 'static,)*
118      {
119          let mut cloned = self.clone();
120          $once_type::new(move |$($arg: $arg_ty),*| cloned($($arg),*))
121      }
122  };
123
124  // ==================== 内部实现:通用部分(Fn trait)====================
125
126  (
127      @impl_common_fn
128      $trait_name:ident < $($generics:ident),* >,
129      $method_name:ident,
130      $closure_trait:path,
131      ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
132  ) => {
133      // 核心方法:直接调用闭包
134      #[inline]
135      fn $method_name(&self, $($arg: $arg_ty),*) $(-> $ret)? {
136          self($($arg),*)
137      }
138
139      // ===== 转换方法:使用 paste 自动推导类型名 =====
140
141      #[inline]
142      fn into_box(self) -> paste::paste! { [<Box $trait_name>] < $($generics),* > }
143      where
144          Self: Sized + 'static,
145      {
146          paste::paste! { [<Box $trait_name>]::new(self) }
147      }
148
149      #[inline]
150      fn into_rc(self) -> paste::paste! { [<Rc $trait_name>] < $($generics),* > }
151      where
152          Self: Sized + 'static,
153      {
154          paste::paste! { [<Rc $trait_name>]::new(self) }
155      }
156
157      #[inline]
158      fn into_fn(self) -> impl $closure_trait
159      where
160          Self: Sized + 'static,
161      {
162          self
163      }
164
165      // into_arc: Fn trait 需要 Send + Sync
166      #[inline]
167      fn into_arc(self) -> paste::paste! { [<Arc $trait_name>] < $($generics),* > }
168      where
169          Self: Sized + Send + Sync + 'static,
170          $($generics: 'static,)*
171      {
172          paste::paste! { [<Arc $trait_name>]::new(self) }
173      }
174
175      // ===== to_* 方法:克隆版本 =====
176
177      #[inline]
178      fn to_box(&self) -> paste::paste! { [<Box $trait_name>] < $($generics),* > }
179      where
180          Self: Clone + Sized + 'static,
181      {
182          paste::paste! { [<Box $trait_name>]::new(self.clone()) }
183      }
184
185      #[inline]
186      fn to_rc(&self) -> paste::paste! { [<Rc $trait_name>] < $($generics),* > }
187      where
188          Self: Clone + Sized + 'static,
189      {
190          paste::paste! { [<Rc $trait_name>]::new(self.clone()) }
191      }
192
193      #[inline]
194      fn to_fn(&self) -> impl $closure_trait
195      where
196          Self: Clone + Sized + 'static,
197      {
198          self.clone()
199      }
200
201      // to_arc: Fn trait 需要 Send + Sync
202      #[inline]
203      fn to_arc(&self) -> paste::paste! { [<Arc $trait_name>] < $($generics),* > }
204      where
205          Self: Clone + Sized + Send + Sync + 'static,
206          $($generics: 'static,)*
207      {
208          paste::paste! { [<Arc $trait_name>]::new(self.clone()) }
209      }
210  };
211
212  // ==================== 内部实现:通用部分(FnMut trait)====================
213
214  (
215      @impl_common_fnmut
216      $trait_name:ident < $($generics:ident),* >,
217      $method_name:ident,
218      $closure_trait:path,
219      ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
220  ) => {
221      // 核心方法:直接调用闭包
222      #[inline]
223      fn $method_name(&mut self, $($arg: $arg_ty),*) $(-> $ret)? {
224          self($($arg),*)
225      }
226
227      // ===== 转换方法:使用 paste 自动推导类型名 =====
228
229      #[inline]
230      fn into_box(self) -> paste::paste! { [<Box $trait_name>] < $($generics),* > }
231      where
232          Self: Sized + 'static,
233      {
234          paste::paste! { [<Box $trait_name>]::new(self) }
235      }
236
237      #[inline]
238      fn into_rc(self) -> paste::paste! { [<Rc $trait_name>] < $($generics),* > }
239      where
240          Self: Sized + 'static,
241      {
242          paste::paste! { [<Rc $trait_name>]::new(self) }
243      }
244
245      #[inline]
246      fn into_fn(self) -> impl $closure_trait
247      where
248          Self: Sized + 'static,
249      {
250          self
251      }
252
253      // into_arc: FnMut trait 只需要 Send
254      #[inline]
255      fn into_arc(self) -> paste::paste! { [<Arc $trait_name>] < $($generics),* > }
256      where
257          Self: Sized + Send + 'static,
258          $($generics: 'static,)*
259      {
260          paste::paste! { [<Arc $trait_name>]::new(self) }
261      }
262
263      // ===== to_* 方法:克隆版本 =====
264
265      #[inline]
266      fn to_box(&self) -> paste::paste! { [<Box $trait_name>] < $($generics),* > }
267      where
268          Self: Clone + Sized + 'static,
269      {
270          paste::paste! { [<Box $trait_name>]::new(self.clone()) }
271      }
272
273      #[inline]
274      fn to_rc(&self) -> paste::paste! { [<Rc $trait_name>] < $($generics),* > }
275      where
276          Self: Clone + Sized + 'static,
277      {
278          paste::paste! { [<Rc $trait_name>]::new(self.clone()) }
279      }
280
281      #[inline]
282      fn to_fn(&self) -> impl $closure_trait
283      where
284          Self: Clone + Sized + 'static,
285      {
286          self.clone()
287      }
288
289      // to_arc: FnMut trait 只需要 Send
290      #[inline]
291      fn to_arc(&self) -> paste::paste! { [<Arc $trait_name>] < $($generics),* > }
292      where
293          Self: Clone + Sized + Send + 'static,
294          $($generics: 'static,)*
295      {
296          let cloned = self.clone();
297          paste::paste! { [<Arc $trait_name>]::new(cloned) }
298      }
299  };
300
301
302  // ==================== 公共接口:参考 impl_rc_conversions 的模式 ====================
303
304  // Regular trait (Fn) - with once conversion
305  (
306      $trait_name:ident < $($generics:ident),* >,
307      $method_name:ident,
308      $once_type:ident,
309      Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
310  ) => {
311      impl<$($generics,)* F> $trait_name<$($generics),*> for F
312      where
313          F: Fn($($arg_ty),*) $(-> $ret)?,
314          $($generics: 'static,)*
315      {
316          // 生成通用方法
317          impl_closure_trait!(
318              @impl_common_fn
319              $trait_name<$($generics),*>,
320              $method_name,
321              Fn($($arg_ty),*) $(-> $ret)?,
322              ($($arg : $arg_ty),*) $(-> $ret)?
323          );
324
325          // 生成 into_once 和 to_once 方法
326          impl_closure_trait!(@into_once_fn_method $once_type, ($($generics),*));
327          impl_closure_trait!(@to_once_fn_method $once_type, ($($generics),*));
328      }
329  };
330
331  // Regular trait (Fn) - without once version
332  (
333      $trait_name:ident < $($generics:ident),* >,
334      $method_name:ident,
335      Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
336  ) => {
337      impl<$($generics,)* F> $trait_name<$($generics),*> for F
338      where
339          F: Fn($($arg_ty),*) $(-> $ret)?,
340          $($generics: 'static,)*
341      {
342          // 生成通用方法(不包含 into_once/to_once)
343          impl_closure_trait!(
344              @impl_common_fn
345              $trait_name<$($generics),*>,
346              $method_name,
347              Fn($($arg_ty),*) $(-> $ret)?,
348              ($($arg : $arg_ty),*) $(-> $ret)?
349          );
350      }
351  };
352
353  // Stateful trait (FnMut) - with once conversion
354  (
355      $trait_name:ident < $($generics:ident),* >,
356      $method_name:ident,
357      $once_type:ident,
358      FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
359  ) => {
360      impl<$($generics,)* F> $trait_name<$($generics),*> for F
361      where
362          F: FnMut($($arg_ty),*) $(-> $ret)?,
363          $($generics: 'static,)*
364      {
365          // 生成通用方法
366          impl_closure_trait!(
367              @impl_common_fnmut
368              $trait_name<$($generics),*>,
369              $method_name,
370              FnMut($($arg_ty),*) $(-> $ret)?,
371              ($($arg : $arg_ty),*) $(-> $ret)?
372          );
373
374          // 生成 into_once 和 to_once 方法
375          impl_closure_trait!(@into_once_fnmut_method $once_type, ($($generics),*), ($($arg : $arg_ty),*) $(-> $ret)?);
376          impl_closure_trait!(@to_once_fnmut_method $once_type, ($($generics),*), ($($arg : $arg_ty),*) $(-> $ret)?);
377      }
378  };
379
380  // Stateful trait (FnMut) - without once version
381  (
382      $trait_name:ident < $($generics:ident),* >,
383      $method_name:ident,
384      FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
385  ) => {
386      impl<$($generics,)* F> $trait_name<$($generics),*> for F
387      where
388          F: FnMut($($arg_ty),*) $(-> $ret)?,
389          $($generics: 'static,)*
390      {
391          // 生成通用方法(不包含 into_once/to_once)
392          impl_closure_trait!(
393              @impl_common_fnmut
394              $trait_name<$($generics),*>,
395              $method_name,
396              FnMut($($arg_ty),*) $(-> $ret)?,
397              ($($arg : $arg_ty),*) $(-> $ret)?
398          );
399      }
400  };
401}
402
403pub(crate) use impl_closure_trait;