Skip to main content

qubit_function/functions/
bi_mutating_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//! # BiMutatingFunction Types
12//!
13//! Provides Rust implementations of bi-mutating-function traits for performing
14//! operations that accept two mutable references and return a result.
15//!
16//! It is similar to the `Fn(&mut T, &mut U) -> R` trait in the standard library.
17//!
18//! This module provides the `BiMutatingFunction<T, U, R>` trait and three
19//! implementations:
20//!
21//! - [`BoxBiMutatingFunction`]: Single ownership, not cloneable
22//! - [`ArcBiMutatingFunction`]: Thread-safe shared ownership, cloneable
23//! - [`RcBiMutatingFunction`]: Single-threaded shared ownership, cloneable
24//!
25
26use std::rc::Rc;
27use std::sync::Arc;
28
29use crate::functions::{
30    bi_mutating_function_once::BoxBiMutatingFunctionOnce,
31    macros::{
32        impl_box_conditional_function,
33        impl_box_function_methods,
34        impl_conditional_function_clone,
35        impl_conditional_function_debug_display,
36        impl_function_clone,
37        impl_function_common_methods,
38        impl_function_constant_method,
39        impl_function_debug_display,
40        impl_shared_conditional_function,
41        impl_shared_function_methods,
42    },
43    mutating_function::MutatingFunction,
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_mutating_function;
59pub use box_bi_mutating_function::BoxBiMutatingFunction;
60mod rc_bi_mutating_function;
61pub use rc_bi_mutating_function::RcBiMutatingFunction;
62mod arc_bi_mutating_function;
63pub use arc_bi_mutating_function::ArcBiMutatingFunction;
64mod fn_bi_mutating_function_ops;
65pub use fn_bi_mutating_function_ops::FnBiMutatingFunctionOps;
66mod box_binary_mutating_function;
67pub use box_binary_mutating_function::BoxBinaryMutatingFunction;
68mod arc_binary_mutating_function;
69pub use arc_binary_mutating_function::ArcBinaryMutatingFunction;
70mod rc_binary_mutating_function;
71pub use rc_binary_mutating_function::RcBinaryMutatingFunction;
72mod box_conditional_bi_mutating_function;
73pub use box_conditional_bi_mutating_function::BoxConditionalBiMutatingFunction;
74mod rc_conditional_bi_mutating_function;
75pub use rc_conditional_bi_mutating_function::RcConditionalBiMutatingFunction;
76mod arc_conditional_bi_mutating_function;
77pub use arc_conditional_bi_mutating_function::ArcConditionalBiMutatingFunction;
78
79// ============================================================================
80// Core Trait
81// ============================================================================
82
83/// BiMutatingFunction trait - performs operations on two mutable references
84///
85/// Defines the behavior of a bi-mutating-function: computing a value of type `R`
86/// from mutable references to types `T` and `U`, potentially modifying both inputs.
87/// This is analogous to `Fn(&mut T, &mut U) -> R` in Rust's standard library.
88///
89/// # Type Parameters
90///
91/// * `T` - The type of the first input value (mutable reference)
92/// * `U` - The type of the second input value (mutable reference)
93/// * `R` - The type of the output value
94///
95pub trait BiMutatingFunction<T, U, R> {
96    /// Applies the bi-mutating-function to two mutable references and returns a result
97    ///
98    /// # Parameters
99    ///
100    /// * `first` - Mutable reference to the first input value
101    /// * `second` - Mutable reference to the second input value
102    ///
103    /// # Returns
104    ///
105    /// The computed output value
106    fn apply(&self, first: &mut T, second: &mut U) -> R;
107
108    /// Converts to BoxBiMutatingFunction
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    /// `BoxBiMutatingFunction`. Types can override this method to provide more
117    /// efficient conversions.
118    ///
119    /// # Returns
120    ///
121    /// Returns `BoxBiMutatingFunction<T, U, R>`
122    fn into_box(self) -> BoxBiMutatingFunction<T, U, R>
123    where
124        Self: Sized + 'static,
125    {
126        BoxBiMutatingFunction::new(move |t, u| self.apply(t, u))
127    }
128
129    /// Converts to RcBiMutatingFunction
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    /// `RcBiMutatingFunction`. Types can override this method to provide more
138    /// efficient conversions.
139    ///
140    /// # Returns
141    ///
142    /// Returns `RcBiMutatingFunction<T, U, R>`
143    fn into_rc(self) -> RcBiMutatingFunction<T, U, R>
144    where
145        Self: Sized + 'static,
146    {
147        RcBiMutatingFunction::new(move |t, u| self.apply(t, u))
148    }
149
150    /// Converts to ArcBiMutatingFunction
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 `ArcBiMutatingFunction`. Types can override this method to provide
159    /// more efficient conversions.
160    ///
161    /// # Returns
162    ///
163    /// Returns `ArcBiMutatingFunction<T, U, R>`
164    fn into_arc(self) -> ArcBiMutatingFunction<T, U, R>
165    where
166        Self: Sized + Send + Sync + 'static,
167    {
168        ArcBiMutatingFunction::new(move |t, u| self.apply(t, u))
169    }
170
171    /// Converts bi-mutating-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(&mut T, &mut U) -> R`
185    fn into_fn(self) -> impl Fn(&mut T, &mut U) -> R
186    where
187        Self: Sized + 'static,
188    {
189        move |t, u| self.apply(t, u)
190    }
191
192    /// Converts to BiMutatingFunctionOnce
193    ///
194    /// **⚠️ Consumes `self`**: The original bi-function becomes unavailable after calling this method.
195    ///
196    /// Converts a reusable bi-mutating-function to a one-time bi-mutating-function that consumes itself on use.
197    /// This enables passing `BiMutatingFunction` to functions that require `BiMutatingFunctionOnce`.
198    ///
199    /// # Returns
200    ///
201    /// Returns a `BoxBiMutatingFunctionOnce<T, U, R>`
202    fn into_once(self) -> BoxBiMutatingFunctionOnce<T, U, R>
203    where
204        Self: Sized + 'static,
205    {
206        BoxBiMutatingFunctionOnce::new(move |t, u| self.apply(t, u))
207    }
208
209    /// Non-consuming conversion to `BoxBiMutatingFunction` using `&self`.
210    ///
211    /// Default implementation clones `self` and delegates to `into_box`.
212    fn to_box(&self) -> BoxBiMutatingFunction<T, U, R>
213    where
214        Self: Sized + Clone + 'static,
215    {
216        self.clone().into_box()
217    }
218
219    /// Non-consuming conversion to `RcBiMutatingFunction` using `&self`.
220    ///
221    /// Default implementation clones `self` and delegates to `into_rc`.
222    fn to_rc(&self) -> RcBiMutatingFunction<T, U, R>
223    where
224        Self: Sized + Clone + 'static,
225    {
226        self.clone().into_rc()
227    }
228
229    /// Non-consuming conversion to `ArcBiMutatingFunction` using `&self`.
230    ///
231    /// Default implementation clones `self` and delegates to `into_arc`.
232    fn to_arc(&self) -> ArcBiMutatingFunction<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(&mut T, &mut U) -> R>` that clones `self` and calls
242    /// `apply` inside the boxed closure.
243    fn to_fn(&self) -> impl Fn(&mut T, &mut U) -> R
244    where
245        Self: Sized + Clone + 'static,
246    {
247        self.clone().into_fn()
248    }
249
250    /// Convert to BiMutatingFunctionOnce 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 `BoxBiMutatingFunctionOnce<T, U, R>`
258    fn to_once(&self) -> BoxBiMutatingFunctionOnce<T, U, R>
259    where
260        Self: Clone + 'static,
261    {
262        self.clone().into_once()
263    }
264}