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/// ```ignore
52/// impl<F, Generics...> TraitName<Generics...> for F
53/// where
54///     F: FnOnce(...),
55/// {
56///     fn method_name(self, ...) {
57///         self(...)
58///     }
59///     fn into_box(self) -> BoxType<...> { ... }
60///     fn into_fn(self) -> impl FnOnce(...) { ... }
61/// }
62/// ```
63///
64/// # Examples
65///
66/// ```ignore
67/// // ConsumerOnce<T>
68/// impl_closure_once_trait!(
69///     ConsumerOnce<T>,
70///     accept,
71///     BoxConsumerOnce,
72///     FnOnce(value: &T)
73/// );
74///
75/// // BiConsumerOnce<T, U>
76/// impl_closure_once_trait!(
77///     BiConsumerOnce<T, U>,
78///     accept,
79///     BoxBiConsumerOnce,
80///     FnOnce(first: &T, second: &U)
81/// );
82///
83/// // FunctionOnce<T, R>
84/// impl_closure_once_trait!(
85///     FunctionOnce<T, R>,
86///     apply,
87///     BoxFunctionOnce,
88///     FnOnce(input: &T) -> R
89/// );
90/// ```
91///
92/// # Author
93///
94/// Haixing Hu
95macro_rules! impl_closure_once_trait {
96  // ==================== Internal Implementation ====================
97
98  // Core implementation: Generate complete trait implementation
99  (
100      @impl
101      $trait_name:ident < $($generics:ident),* >,
102      $method_name:ident,
103      $box_type:ident,
104      ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
105  ) => {
106      impl<F, $($generics),*> $trait_name<$($generics),*> for F
107      where
108          F: FnOnce($($arg_ty),*) $(-> $ret)?,
109      {
110          // Core method: Direct closure call
111          #[inline]
112          fn $method_name(self, $($arg : $arg_ty),*) $(-> $ret)? {
113              self($($arg),*)
114          }
115
116          // into_box: Convert to Box type
117          #[inline]
118          fn into_box(self) -> $box_type<$($generics),*>
119          where
120              Self: Sized + 'static,
121              $($generics: 'static),*
122          {
123              $box_type::new(self)
124          }
125
126          // into_fn: Convert to closure (always return self directly since F is already FnOnce)
127          #[inline]
128          fn into_fn(self) -> impl FnOnce($($arg_ty),*) $(-> $ret)?
129          where
130              Self: Sized + 'static,
131          {
132              // F is already FnOnce with the correct signature, return directly (zero cost)
133              self
134          }
135      }
136  };
137
138  // ==================== Public Interface ====================
139
140  // No return value version
141  (
142      $trait_name:ident < $($generics:ident),* >,
143      $method_name:ident,
144      $box_type:ident,
145      FnOnce($($arg:ident : $arg_ty:ty),*)
146  ) => {
147      impl_closure_once_trait!(
148          @impl
149          $trait_name<$($generics),*>,
150          $method_name,
151          $box_type,
152          ($($arg : $arg_ty),*)
153      );
154  };
155
156  // With return value version
157  (
158      $trait_name:ident < $($generics:ident),* >,
159      $method_name:ident,
160      $box_type:ident,
161      FnOnce($($arg:ident : $arg_ty:ty),*) -> $ret:ty
162  ) => {
163      impl_closure_once_trait!(
164          @impl
165          $trait_name<$($generics),*>,
166          $method_name,
167          $box_type,
168          ($($arg : $arg_ty),*) -> $ret
169      );
170  };
171}
172
173pub(crate) use impl_closure_once_trait;