qubit_function/functions/bi_function.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9
10//! # BiFunction Types
11//!
12//! Provides Rust implementations of bi-function traits for computing output values
13//! from two input references. BiFunctions borrow input values (not consuming them)
14//! and produce output values.
15//!
16//! It is similar to the `Fn(&T, &U) -> R` trait in the standard library.
17//!
18//! This module provides the `BiFunction<T, U, R>` trait and three
19//! implementations:
20//!
21//! - [`BoxBiFunction`]: Single ownership, not cloneable
22//! - [`ArcBiFunction`]: Thread-safe shared ownership, cloneable
23//! - [`RcBiFunction`]: Single-threaded shared ownership, cloneable
24//!
25//! # Author
26//!
27//! Haixing Hu
28use std::rc::Rc;
29use std::sync::Arc;
30
31use crate::functions::{
32 bi_function_once::BoxBiFunctionOnce,
33 function::Function,
34 macros::{
35 impl_box_conditional_function,
36 impl_box_function_methods,
37 impl_conditional_function_clone,
38 impl_conditional_function_debug_display,
39 impl_function_clone,
40 impl_function_common_methods,
41 impl_function_constant_method,
42 impl_function_debug_display,
43 impl_shared_conditional_function,
44 impl_shared_function_methods,
45 },
46};
47use crate::macros::{
48 impl_arc_conversions,
49 impl_box_conversions,
50 impl_closure_trait,
51 impl_rc_conversions,
52};
53use crate::predicates::bi_predicate::{
54 ArcBiPredicate,
55 BiPredicate,
56 BoxBiPredicate,
57 RcBiPredicate,
58};
59
60mod box_bi_function;
61pub use box_bi_function::BoxBiFunction;
62mod rc_bi_function;
63pub use rc_bi_function::RcBiFunction;
64mod arc_bi_function;
65pub use arc_bi_function::ArcBiFunction;
66mod fn_bi_function_ops;
67pub use fn_bi_function_ops::FnBiFunctionOps;
68mod box_binary_function;
69pub use box_binary_function::BoxBinaryFunction;
70mod arc_binary_function;
71pub use arc_binary_function::ArcBinaryFunction;
72mod rc_binary_function;
73pub use rc_binary_function::RcBinaryFunction;
74mod box_conditional_bi_function;
75pub use box_conditional_bi_function::BoxConditionalBiFunction;
76mod rc_conditional_bi_function;
77pub use rc_conditional_bi_function::RcConditionalBiFunction;
78mod arc_conditional_bi_function;
79pub use arc_conditional_bi_function::ArcConditionalBiFunction;
80
81// ============================================================================
82// Core Trait
83// ============================================================================
84
85/// BiFunction trait - computes output from two input references
86///
87/// Defines the behavior of a bi-function: computing a value of type `R`
88/// from references to types `T` and `U` without consuming the inputs. This is analogous to
89/// `Fn(&T, &U) -> R` in Rust's standard library, similar to Java's `BiFunction<T, U, R>`.
90///
91/// # Type Parameters
92///
93/// * `T` - The type of the first input value (borrowed)
94/// * `U` - The type of the second input value (borrowed)
95/// * `R` - The type of the output value
96///
97/// # Author
98///
99/// Haixing Hu
100pub trait BiFunction<T, U, R> {
101 /// Applies the bi-function to two input references to produce an output value
102 ///
103 /// # Parameters
104 ///
105 /// * `first` - Reference to the first input value
106 /// * `second` - Reference to the second input value
107 ///
108 /// # Returns
109 ///
110 /// The computed output value
111 fn apply(&self, first: &T, second: &U) -> R;
112
113 /// Converts to BoxBiFunction
114 ///
115 /// **⚠️ Consumes `self`**: The original bi-function becomes
116 /// unavailable after calling this method.
117 ///
118 /// # Default Implementation
119 ///
120 /// The default implementation wraps `self` in a `Box` and creates a
121 /// `BoxBiFunction`. Types can override this method to provide more
122 /// efficient conversions.
123 ///
124 /// # Returns
125 ///
126 /// Returns `BoxBiFunction<T, U, R>`
127 fn into_box(self) -> BoxBiFunction<T, U, R>
128 where
129 Self: Sized + 'static,
130 {
131 BoxBiFunction::new(move |t, u| self.apply(t, u))
132 }
133
134 /// Converts to RcBiFunction
135 ///
136 /// **⚠️ Consumes `self`**: The original bi-function becomes
137 /// unavailable after calling this method.
138 ///
139 /// # Default Implementation
140 ///
141 /// The default implementation wraps `self` in an `Rc` and creates an
142 /// `RcBiFunction`. Types can override this method to provide more
143 /// efficient conversions.
144 ///
145 /// # Returns
146 ///
147 /// Returns `RcBiFunction<T, U, R>`
148 fn into_rc(self) -> RcBiFunction<T, U, R>
149 where
150 Self: Sized + 'static,
151 {
152 RcBiFunction::new(move |t, u| self.apply(t, u))
153 }
154
155 /// Converts to ArcBiFunction
156 ///
157 /// **⚠️ Consumes `self`**: The original bi-function becomes
158 /// unavailable after calling this method.
159 ///
160 /// # Default Implementation
161 ///
162 /// The default implementation wraps `self` in an `Arc` and creates
163 /// an `ArcBiFunction`. Types can override this method to provide
164 /// more efficient conversions.
165 ///
166 /// # Returns
167 ///
168 /// Returns `ArcBiFunction<T, U, R>`
169 fn into_arc(self) -> ArcBiFunction<T, U, R>
170 where
171 Self: Sized + Send + Sync + 'static,
172 {
173 ArcBiFunction::new(move |t, u| self.apply(t, u))
174 }
175
176 /// Converts bi-function to a closure
177 ///
178 /// **⚠️ Consumes `self`**: The original bi-function becomes
179 /// unavailable after calling this method.
180 ///
181 /// # Default Implementation
182 ///
183 /// The default implementation creates a closure that captures `self`
184 /// and calls its `apply` method. Types can override this method
185 /// to provide more efficient conversions.
186 ///
187 /// # Returns
188 ///
189 /// Returns a closure that implements `Fn(&T, &U) -> R`
190 fn into_fn(self) -> impl Fn(&T, &U) -> R
191 where
192 Self: Sized + 'static,
193 {
194 move |t, u| self.apply(t, u)
195 }
196
197 /// Converts to BiFunctionOnce
198 ///
199 /// **⚠️ Consumes `self`**: The original bi-function becomes unavailable after calling this method.
200 ///
201 /// Converts a reusable bi-function to a one-time bi-function that consumes itself on use.
202 /// This enables passing `BiFunction` to functions that require `BiFunctionOnce`.
203 ///
204 /// # Returns
205 ///
206 /// Returns a `BoxBiFunctionOnce<T, U, R>`
207 fn into_once(self) -> BoxBiFunctionOnce<T, U, R>
208 where
209 Self: Sized + 'static,
210 {
211 BoxBiFunctionOnce::new(move |t, u| self.apply(t, u))
212 }
213
214 /// Non-consuming conversion to `BoxBiFunction` using `&self`.
215 ///
216 /// Default implementation clones `self` and delegates to `into_box`.
217 fn to_box(&self) -> BoxBiFunction<T, U, R>
218 where
219 Self: Sized + Clone + 'static,
220 {
221 self.clone().into_box()
222 }
223
224 /// Non-consuming conversion to `RcBiFunction` using `&self`.
225 ///
226 /// Default implementation clones `self` and delegates to `into_rc`.
227 fn to_rc(&self) -> RcBiFunction<T, U, R>
228 where
229 Self: Sized + Clone + 'static,
230 {
231 self.clone().into_rc()
232 }
233
234 /// Non-consuming conversion to `ArcBiFunction` using `&self`.
235 ///
236 /// Default implementation clones `self` and delegates to `into_arc`.
237 fn to_arc(&self) -> ArcBiFunction<T, U, R>
238 where
239 Self: Sized + Clone + Send + Sync + 'static,
240 {
241 self.clone().into_arc()
242 }
243
244 /// Non-consuming conversion to a boxed function using `&self`.
245 ///
246 /// Returns a `Box<dyn Fn(&T, &U) -> R>` that clones `self` and calls
247 /// `apply` inside the boxed closure.
248 fn to_fn(&self) -> impl Fn(&T, &U) -> R
249 where
250 Self: Sized + Clone + 'static,
251 {
252 self.clone().into_fn()
253 }
254
255 /// Convert to BiFunctionOnce without consuming self
256 ///
257 /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
258 /// Clones the current bi-function and converts the clone to a one-time bi-function.
259 ///
260 /// # Returns
261 ///
262 /// Returns a `BoxBiFunctionOnce<T, U, R>`
263 fn to_once(&self) -> BoxBiFunctionOnce<T, U, R>
264 where
265 Self: Clone + 'static,
266 {
267 self.clone().into_once()
268 }
269}