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