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}