Skip to main content

qubit_function/functions/
bi_mutating_function.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9
10//! # BiMutatingFunction Types
11//!
12//! Provides Rust implementations of bi-mutating-function traits for performing
13//! operations that accept two mutable references and return a result.
14//!
15//! It is similar to the `Fn(&mut T, &mut U) -> R` trait in the standard library.
16//!
17//! This module provides the `BiMutatingFunction<T, U, R>` trait and three
18//! implementations:
19//!
20//! - [`BoxBiMutatingFunction`]: Single ownership, not cloneable
21//! - [`ArcBiMutatingFunction`]: Thread-safe shared ownership, cloneable
22//! - [`RcBiMutatingFunction`]: Single-threaded shared ownership, cloneable
23//!
24//! # Author
25//!
26//! Haixing Hu
27
28use std::rc::Rc;
29use std::sync::Arc;
30
31use crate::functions::{
32    bi_mutating_function_once::BoxBiMutatingFunctionOnce,
33    macros::{
34        impl_box_conditional_function,
35        impl_box_function_methods,
36        impl_conditional_function_clone,
37        impl_conditional_function_debug_display,
38        impl_function_clone,
39        impl_function_common_methods,
40        impl_function_constant_method,
41        impl_function_debug_display,
42        impl_shared_conditional_function,
43        impl_shared_function_methods,
44    },
45    mutating_function::MutatingFunction,
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_mutating_function;
61pub use box_bi_mutating_function::BoxBiMutatingFunction;
62mod rc_bi_mutating_function;
63pub use rc_bi_mutating_function::RcBiMutatingFunction;
64mod arc_bi_mutating_function;
65pub use arc_bi_mutating_function::ArcBiMutatingFunction;
66mod fn_bi_mutating_function_ops;
67pub use fn_bi_mutating_function_ops::FnBiMutatingFunctionOps;
68mod box_binary_mutating_function;
69pub use box_binary_mutating_function::BoxBinaryMutatingFunction;
70mod arc_binary_mutating_function;
71pub use arc_binary_mutating_function::ArcBinaryMutatingFunction;
72mod rc_binary_mutating_function;
73pub use rc_binary_mutating_function::RcBinaryMutatingFunction;
74mod box_conditional_bi_mutating_function;
75pub use box_conditional_bi_mutating_function::BoxConditionalBiMutatingFunction;
76mod rc_conditional_bi_mutating_function;
77pub use rc_conditional_bi_mutating_function::RcConditionalBiMutatingFunction;
78mod arc_conditional_bi_mutating_function;
79pub use arc_conditional_bi_mutating_function::ArcConditionalBiMutatingFunction;
80
81// ============================================================================
82// Core Trait
83// ============================================================================
84
85/// BiMutatingFunction trait - performs operations on two mutable references
86///
87/// Defines the behavior of a bi-mutating-function: computing a value of type `R`
88/// from mutable references to types `T` and `U`, potentially modifying both inputs.
89/// This is analogous to `Fn(&mut T, &mut U) -> R` in Rust's standard library.
90///
91/// # Type Parameters
92///
93/// * `T` - The type of the first input value (mutable reference)
94/// * `U` - The type of the second input value (mutable reference)
95/// * `R` - The type of the output value
96///
97/// # Author
98///
99/// Haixing Hu
100pub trait BiMutatingFunction<T, U, R> {
101    /// Applies the bi-mutating-function to two mutable references and returns a result
102    ///
103    /// # Parameters
104    ///
105    /// * `first` - Mutable reference to the first input value
106    /// * `second` - Mutable reference to the second input value
107    ///
108    /// # Returns
109    ///
110    /// The computed output value
111    fn apply(&self, first: &mut T, second: &mut U) -> R;
112
113    /// Converts to BoxBiMutatingFunction
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    /// `BoxBiMutatingFunction`. Types can override this method to provide more
122    /// efficient conversions.
123    ///
124    /// # Returns
125    ///
126    /// Returns `BoxBiMutatingFunction<T, U, R>`
127    fn into_box(self) -> BoxBiMutatingFunction<T, U, R>
128    where
129        Self: Sized + 'static,
130    {
131        BoxBiMutatingFunction::new(move |t, u| self.apply(t, u))
132    }
133
134    /// Converts to RcBiMutatingFunction
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    /// `RcBiMutatingFunction`. Types can override this method to provide more
143    /// efficient conversions.
144    ///
145    /// # Returns
146    ///
147    /// Returns `RcBiMutatingFunction<T, U, R>`
148    fn into_rc(self) -> RcBiMutatingFunction<T, U, R>
149    where
150        Self: Sized + 'static,
151    {
152        RcBiMutatingFunction::new(move |t, u| self.apply(t, u))
153    }
154
155    /// Converts to ArcBiMutatingFunction
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 `ArcBiMutatingFunction`. Types can override this method to provide
164    /// more efficient conversions.
165    ///
166    /// # Returns
167    ///
168    /// Returns `ArcBiMutatingFunction<T, U, R>`
169    fn into_arc(self) -> ArcBiMutatingFunction<T, U, R>
170    where
171        Self: Sized + Send + Sync + 'static,
172    {
173        ArcBiMutatingFunction::new(move |t, u| self.apply(t, u))
174    }
175
176    /// Converts bi-mutating-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(&mut T, &mut U) -> R`
190    fn into_fn(self) -> impl Fn(&mut T, &mut U) -> R
191    where
192        Self: Sized + 'static,
193    {
194        move |t, u| self.apply(t, u)
195    }
196
197    /// Converts to BiMutatingFunctionOnce
198    ///
199    /// **⚠️ Consumes `self`**: The original bi-function becomes unavailable after calling this method.
200    ///
201    /// Converts a reusable bi-mutating-function to a one-time bi-mutating-function that consumes itself on use.
202    /// This enables passing `BiMutatingFunction` to functions that require `BiMutatingFunctionOnce`.
203    ///
204    /// # Returns
205    ///
206    /// Returns a `BoxBiMutatingFunctionOnce<T, U, R>`
207    fn into_once(self) -> BoxBiMutatingFunctionOnce<T, U, R>
208    where
209        Self: Sized + 'static,
210    {
211        BoxBiMutatingFunctionOnce::new(move |t, u| self.apply(t, u))
212    }
213
214    /// Non-consuming conversion to `BoxBiMutatingFunction` using `&self`.
215    ///
216    /// Default implementation clones `self` and delegates to `into_box`.
217    fn to_box(&self) -> BoxBiMutatingFunction<T, U, R>
218    where
219        Self: Sized + Clone + 'static,
220    {
221        self.clone().into_box()
222    }
223
224    /// Non-consuming conversion to `RcBiMutatingFunction` using `&self`.
225    ///
226    /// Default implementation clones `self` and delegates to `into_rc`.
227    fn to_rc(&self) -> RcBiMutatingFunction<T, U, R>
228    where
229        Self: Sized + Clone + 'static,
230    {
231        self.clone().into_rc()
232    }
233
234    /// Non-consuming conversion to `ArcBiMutatingFunction` using `&self`.
235    ///
236    /// Default implementation clones `self` and delegates to `into_arc`.
237    fn to_arc(&self) -> ArcBiMutatingFunction<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(&mut T, &mut U) -> R>` that clones `self` and calls
247    /// `apply` inside the boxed closure.
248    fn to_fn(&self) -> impl Fn(&mut T, &mut U) -> R
249    where
250        Self: Sized + Clone + 'static,
251    {
252        self.clone().into_fn()
253    }
254
255    /// Convert to BiMutatingFunctionOnce 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 `BoxBiMutatingFunctionOnce<T, U, R>`
263    fn to_once(&self) -> BoxBiMutatingFunctionOnce<T, U, R>
264    where
265        Self: Clone + 'static,
266    {
267        self.clone().into_once()
268    }
269}