Skip to main content

qubit_function/functions/
bi_mutating_function_once.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//! # BiMutatingFunctionOnce Types
12//!
13//! Provides Rust implementations of consuming bi-mutating-function traits similar to
14//! Rust's `FnOnce(&mut T, &mut U) -> R` trait, but with value-oriented semantics for functional
15//! programming patterns with two mutable input references.
16//!
17//! This module provides the `BiMutatingFunctionOnce<T, U, R>` trait and one-time use
18//! implementations:
19//!
20//! - [`BoxBiMutatingFunctionOnce`]: Single ownership, one-time use
21//!
22use crate::functions::{
23    macros::{
24        impl_box_conditional_function,
25        impl_box_function_methods,
26        impl_conditional_function_debug_display,
27        impl_function_common_methods,
28        impl_function_constant_method,
29        impl_function_debug_display,
30    },
31    mutating_function_once::MutatingFunctionOnce,
32};
33use crate::macros::{
34    impl_box_once_conversions,
35    impl_closure_once_trait,
36};
37use crate::predicates::bi_predicate::{
38    BiPredicate,
39    BoxBiPredicate,
40};
41
42mod box_bi_mutating_function_once;
43pub use box_bi_mutating_function_once::BoxBiMutatingFunctionOnce;
44mod fn_bi_mutating_function_once_ops;
45pub use fn_bi_mutating_function_once_ops::FnBiMutatingFunctionOnceOps;
46mod box_conditional_bi_mutating_function_once;
47pub use box_conditional_bi_mutating_function_once::BoxConditionalBiMutatingFunctionOnce;
48
49// ============================================================================
50// Core Trait
51// ============================================================================
52
53/// BiMutatingFunctionOnce trait - consuming bi-mutating-function that takes
54/// mutable references
55///
56/// Defines the behavior of a consuming bi-mutating-function: computing a value of
57/// type `R` from mutable references to types `T` and `U` by taking ownership of self.
58/// This trait is analogous to `FnOnce(&mut T, &mut U) -> R`.
59///
60/// # Type Parameters
61///
62/// * `T` - The type of the first input value (mutable reference)
63/// * `U` - The type of the second input value (mutable reference)
64/// * `R` - The type of the output value
65///
66pub trait BiMutatingFunctionOnce<T, U, R> {
67    /// Computes output from two mutable references, consuming self
68    ///
69    /// # Parameters
70    ///
71    /// * `first` - Mutable reference to the first input value
72    /// * `second` - Mutable reference to the second input value
73    ///
74    /// # Returns
75    ///
76    /// The computed output value
77    fn apply(self, first: &mut T, second: &mut U) -> R;
78
79    /// Converts to BoxBiMutatingFunctionOnce
80    ///
81    /// **⚠️ Consumes `self`**: The original bi-function becomes unavailable
82    /// after calling this method.
83    ///
84    /// # Returns
85    ///
86    /// Returns `BoxBiMutatingFunctionOnce<T, U, R>`
87    fn into_box(self) -> BoxBiMutatingFunctionOnce<T, U, R>
88    where
89        Self: Sized + 'static,
90    {
91        BoxBiMutatingFunctionOnce::new(move |t: &mut T, u: &mut U| self.apply(t, u))
92    }
93
94    /// Converts bi-mutating-function to a closure
95    ///
96    /// **⚠️ Consumes `self`**: The original bi-function becomes unavailable
97    /// after calling this method.
98    ///
99    /// # Returns
100    ///
101    /// Returns a closure that implements `FnOnce(&mut T, &mut U) -> R`
102    fn into_fn(self) -> impl FnOnce(&mut T, &mut U) -> R
103    where
104        Self: Sized + 'static,
105    {
106        move |t: &mut T, u: &mut U| self.apply(t, u)
107    }
108
109    /// Converts bi-mutating-function to a boxed function pointer
110    ///
111    /// **📌 Borrows `&self`**: The original bi-function remains usable
112    /// after calling this method.
113    ///
114    /// # Returns
115    ///
116    /// Returns a boxed function pointer that implements `FnOnce(&mut T, &mut U) -> R`
117    ///
118    /// # Examples
119    ///
120    /// ```rust
121    /// use qubit_function::BiMutatingFunctionOnce;
122    ///
123    /// let swap_and_sum = |x: &mut i32, y: &mut i32| {
124    ///     let temp = *x;
125    ///     *x = *y;
126    ///     *y = temp;
127    ///     *x + *y
128    /// };
129    /// let func = swap_and_sum.to_box();
130    /// let mut a = 20;
131    /// let mut b = 22;
132    /// assert_eq!(func.apply(&mut a, &mut b), 42);
133    /// ```
134    fn to_box(&self) -> BoxBiMutatingFunctionOnce<T, U, R>
135    where
136        Self: Clone + 'static,
137    {
138        self.clone().into_box()
139    }
140
141    /// Converts bi-mutating-function to a closure
142    ///
143    /// **📌 Borrows `&self`**: The original bi-function remains usable
144    /// after calling this method.
145    ///
146    /// # Returns
147    ///
148    /// Returns a closure that implements `FnOnce(&mut T, &mut U) -> R`
149    ///
150    /// # Examples
151    ///
152    /// ```rust
153    /// use qubit_function::BiMutatingFunctionOnce;
154    ///
155    /// let swap_and_sum = |x: &mut i32, y: &mut i32| {
156    ///     let temp = *x;
157    ///     *x = *y;
158    ///     *y = temp;
159    ///     *x + *y
160    /// };
161    /// let func = swap_and_sum.to_fn();
162    /// let mut a = 20;
163    /// let mut b = 22;
164    /// assert_eq!(func(&mut a, &mut b), 42);
165    /// ```
166    fn to_fn(&self) -> impl FnOnce(&mut T, &mut U) -> R
167    where
168        Self: Clone + 'static,
169    {
170        self.clone().into_fn()
171    }
172}