qubit_function/functions/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//! # MutatingFunctionOnce Types
11//!
12//! Provides Java-like one-time `MutatingFunction` interface implementations
13//! for performing operations that consume self, accept a mutable reference,
14//! and return a result.
15//!
16//! It is similar to the `FnOnce(&mut T) -> R` trait in the standard library.
17//!
18//! This module provides a unified `MutatingFunctionOnce` trait and a
19//! Box-based single ownership implementation:
20//!
21//! - **`BoxMutatingFunctionOnce<T, R>`**: Box-based single ownership
22//! implementation for one-time use scenarios
23//!
24//! # Design Philosophy
25//!
26//! The key difference between `MutatingFunctionOnce` and
27//! `MutatingFunction`:
28//!
29//! - **MutatingFunction**: `&self`, can be called multiple times, uses
30//! `Fn(&mut T) -> R`
31//! - **MutatingFunctionOnce**: `self`, can only be called once, uses
32//! `FnOnce(&mut T) -> R`
33//!
34//! ## MutatingFunctionOnce vs MutatingFunction
35//!
36//! | Feature | MutatingFunction | MutatingFunctionOnce |
37//! |---------|------------------|----------------------|
38//! | **Self Parameter** | `&self` | `self` |
39//! | **Call Count** | Multiple | Once |
40//! | **Closure Type** | `Fn(&mut T) -> R` | `FnOnce(&mut T) -> R` |
41//! | **Use Cases** | Repeatable operations | One-time resource
42//! transfers |
43//!
44//! # Why MutatingFunctionOnce?
45//!
46//! Core value of MutatingFunctionOnce:
47//!
48//! 1. **Store FnOnce closures**: Allows moving captured variables
49//! 2. **Delayed execution**: Store in data structures, execute later
50//! 3. **Resource transfer**: Suitable for scenarios requiring ownership
51//! transfer
52//! 4. **Return results**: Unlike MutatorOnce, returns information about the
53//! operation
54//!
55//! # Why Only Box Variant?
56//!
57//! - **Arc/Rc conflicts with FnOnce semantics**: FnOnce can only be called
58//! once, while shared ownership implies multiple references
59//! - **Box is perfect match**: Single ownership aligns perfectly with
60//! one-time call semantics
61//!
62//! # Use Cases
63//!
64//! ## BoxMutatingFunctionOnce
65//!
66//! - Post-initialization callbacks (moving data, returning status)
67//! - Resource transfer with result (moving Vec, returning old value)
68//! - One-time complex operations (requiring moved capture variables)
69//! - Validation with fixes (fix data once, return validation result)
70//!
71//! # Examples
72//!
73//! ## Basic Usage
74//!
75//! ```rust
76//! use qubit_function::{BoxMutatingFunctionOnce, MutatingFunctionOnce};
77//!
78//! let data = vec![1, 2, 3];
79//! let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
80//! let old_len = x.len();
81//! x.extend(data); // Move data
82//! old_len
83//! });
84//!
85//! let mut target = vec![0];
86//! let old_len = func.apply(&mut target);
87//! assert_eq!(old_len, 1);
88//! assert_eq!(target, vec![0, 1, 2, 3]);
89//! ```
90//!
91//! ## Method Chaining
92//!
93//! ```rust
94//! use qubit_function::{BoxMutatingFunctionOnce, MutatingFunctionOnce};
95//!
96//! let data1 = vec![1, 2];
97//!
98//! let chained = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
99//! x.extend(data1);
100//! x.len()
101//! })
102//! .and_then(|len: &usize| len + 2);
103//!
104//! let mut target = vec![0];
105//! let final_len = chained.apply(&mut target);
106//! assert_eq!(final_len, 5);
107//! assert_eq!(target, vec![0, 1, 2]);
108//! ```
109//!
110//! ## Validation Pattern
111//!
112//! ```rust
113//! use qubit_function::{BoxMutatingFunctionOnce, MutatingFunctionOnce};
114//!
115//! struct Data {
116//! value: i32,
117//! }
118//!
119//! let validator = BoxMutatingFunctionOnce::new(|data: &mut Data| {
120//! if data.value < 0 {
121//! data.value = 0;
122//! Err("Fixed negative value")
123//! } else {
124//! Ok("Valid")
125//! }
126//! });
127//!
128//! let mut data = Data { value: -5 };
129//! let result = validator.apply(&mut data);
130//! assert_eq!(data.value, 0);
131//! assert!(result.is_err());
132//! ```
133//!
134use crate::functions::{
135 function_once::FunctionOnce,
136 macros::{
137 impl_box_conditional_function,
138 impl_box_function_methods,
139 impl_conditional_function_debug_display,
140 impl_fn_ops_trait,
141 impl_function_common_methods,
142 impl_function_debug_display,
143 impl_function_identity_method,
144 },
145};
146use crate::macros::{
147 impl_box_once_conversions,
148 impl_closure_once_trait,
149};
150use crate::predicates::predicate::{
151 BoxPredicate,
152 Predicate,
153};
154
155mod box_mutating_function_once;
156pub use box_mutating_function_once::BoxMutatingFunctionOnce;
157mod box_conditional_mutating_function_once;
158pub use box_conditional_mutating_function_once::BoxConditionalMutatingFunctionOnce;
159mod fn_mutating_function_once_ops;
160pub use fn_mutating_function_once_ops::FnMutatingFunctionOnceOps;
161
162// =======================================================================
163// 1. MutatingFunctionOnce Trait - One-time Function Interface
164// =======================================================================
165
166/// MutatingFunctionOnce trait - One-time mutating function interface
167///
168/// It is similar to the `FnOnce(&mut T) -> R` trait in the standard library.
169///
170/// Defines the core behavior of all one-time mutating function types.
171/// Performs operations that consume self, accept a mutable reference,
172/// potentially modify it, and return a result.
173///
174/// This trait is automatically implemented by:
175/// - All closures implementing `FnOnce(&mut T) -> R`
176/// - `BoxMutatingFunctionOnce<T, R>`
177///
178/// # Design Rationale
179///
180/// This trait provides a unified abstraction for one-time mutating function
181/// operations. The key difference from `MutatingFunction`:
182/// - `MutatingFunction` uses `&self`, can be called multiple times
183/// - `MutatingFunctionOnce` uses `self`, can only be called once
184///
185/// # Features
186///
187/// - **Unified Interface**: All one-time mutating functions share the same
188/// `apply` method signature
189/// - **Automatic Implementation**: Closures automatically implement this
190/// trait with zero overhead
191/// - **Type Conversions**: Provides `into_box` method for type conversion
192/// - **Generic Programming**: Write functions that work with any one-time
193/// mutating function type
194///
195/// # Examples
196///
197/// ## Generic Function
198///
199/// ```rust
200/// use qubit_function::{MutatingFunctionOnce, BoxMutatingFunctionOnce};
201///
202/// fn apply<F: MutatingFunctionOnce<Vec<i32>, usize>>(
203/// func: F,
204/// initial: Vec<i32>
205/// ) -> (Vec<i32>, usize) {
206/// let mut val = initial;
207/// let result = func.apply(&mut val);
208/// (val, result)
209/// }
210///
211/// let data = vec![1, 2, 3];
212/// let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
213/// let old_len = x.len();
214/// x.extend(data);
215/// old_len
216/// });
217/// let (vec, old_len) = apply(func, vec![0]);
218/// assert_eq!(vec, vec![0, 1, 2, 3]);
219/// assert_eq!(old_len, 1);
220/// ```
221///
222/// ## Type Conversion
223///
224/// ```rust
225/// use qubit_function::MutatingFunctionOnce;
226///
227/// let data = vec![1, 2, 3];
228/// let closure = move |x: &mut Vec<i32>| {
229/// let old_len = x.len();
230/// x.extend(data);
231/// old_len
232/// };
233/// let box_func = closure.into_box();
234/// ```
235///
236pub trait MutatingFunctionOnce<T, R> {
237 /// Performs the one-time mutating function operation
238 ///
239 /// Consumes self and executes an operation on the given mutable
240 /// reference, potentially modifying it, and returns a result. The
241 /// operation can only be called once.
242 ///
243 /// # Parameters
244 ///
245 /// * `t - A mutable reference to the input value
246 ///
247 /// # Returns
248 ///
249 /// The computed result value
250 ///
251 /// # Examples
252 ///
253 /// ```rust
254 /// use qubit_function::{MutatingFunctionOnce,
255 /// BoxMutatingFunctionOnce};
256 ///
257 /// let data = vec![1, 2, 3];
258 /// let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
259 /// let old_len = x.len();
260 /// x.extend(data);
261 /// old_len
262 /// });
263 ///
264 /// let mut target = vec![0];
265 /// let old_len = func.apply(&mut target);
266 /// assert_eq!(old_len, 1);
267 /// assert_eq!(target, vec![0, 1, 2, 3]);
268 /// ```
269 fn apply(self, t: &mut T) -> R;
270
271 /// Converts to `BoxMutatingFunctionOnce` (consuming)
272 ///
273 /// Consumes `self` and returns an owned `BoxMutatingFunctionOnce<T, R>`.
274 /// The default implementation simply wraps the consuming
275 /// `apply(self, &mut T)` call in a `Box<dyn FnOnce(&mut T) -> R>`.
276 /// Types that can provide a cheaper or identity conversion (for example
277 /// `BoxMutatingFunctionOnce` itself) should override this method.
278 ///
279 /// # Note
280 ///
281 /// - This method consumes the source value.
282 /// - Implementors may return `self` directly when `Self` is already a
283 /// `BoxMutatingFunctionOnce<T, R>` to avoid the extra wrapper
284 /// allocation.
285 fn into_box(self) -> BoxMutatingFunctionOnce<T, R>
286 where
287 Self: Sized + 'static,
288 {
289 BoxMutatingFunctionOnce::new(move |t| self.apply(t))
290 }
291
292 /// Converts to a consuming closure `FnOnce(&mut T) -> R`
293 ///
294 /// Consumes `self` and returns a closure that, when invoked, calls
295 /// `apply(self, &mut T)`. This is the default, straightforward
296 /// implementation; types that can produce a more direct function pointer
297 /// or avoid additional captures may override it.
298 fn into_fn(self) -> impl FnOnce(&mut T) -> R
299 where
300 Self: Sized + 'static,
301 {
302 move |t| self.apply(t)
303 }
304
305 /// Non-consuming adapter to `BoxMutatingFunctionOnce`
306 ///
307 /// Creates a `BoxMutatingFunctionOnce<T, R>` that does not consume
308 /// `self`. The default implementation requires `Self: Clone` and clones
309 /// the receiver for the stored closure; the clone is consumed when the
310 /// boxed function is invoked. Types that can provide a zero-cost adapter
311 /// (for example clonable closures) should override this method to avoid
312 /// unnecessary allocations.
313 fn to_box(&self) -> BoxMutatingFunctionOnce<T, R>
314 where
315 Self: Sized + Clone + 'static,
316 {
317 self.clone().into_box()
318 }
319
320 /// Non-consuming adapter to a callable `FnOnce(&mut T) -> R`
321 ///
322 /// Returns a closure that does not consume `self`. The default requires
323 /// `Self: Clone` and clones `self` for the captured closure; the clone is
324 /// consumed when the returned closure is invoked. Implementors may
325 /// provide more efficient adapters for specific types.
326 fn to_fn(&self) -> impl FnOnce(&mut T) -> R
327 where
328 Self: Sized + Clone + 'static,
329 {
330 self.clone().into_fn()
331 }
332}