qubit_function/transformers/transformer_once.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # TransformerOnce Types
10//!
11//! Provides Rust implementations of consuming transformer traits similar to
12//! Rust's `FnOnce` trait, but with value-oriented semantics for functional
13//! programming patterns.
14//!
15//! This module provides the `TransformerOnce<T, R>` trait and one-time use
16//! implementations:
17//!
18//! - [`BoxTransformerOnce`]: Single ownership, one-time use
19//!
20//! # Author
21//!
22//! Haixing Hu
23
24use crate::macros::{
25 impl_box_once_conversions,
26 impl_closure_once_trait,
27};
28use crate::predicates::predicate::{
29 BoxPredicate,
30 Predicate,
31};
32use crate::transformers::macros::{
33 impl_box_conditional_transformer,
34 impl_box_transformer_methods,
35 impl_conditional_transformer_debug_display,
36 impl_transformer_common_methods,
37 impl_transformer_constant_method,
38 impl_transformer_debug_display,
39};
40
41// ============================================================================
42// Core Trait
43// ============================================================================
44
45/// TransformerOnce trait - consuming transformation that takes ownership
46///
47/// Defines the behavior of a consuming transformer: converting a value of
48/// type `T` to a value of type `R` by taking ownership of both self and the
49/// input. This trait is analogous to `FnOnce(T) -> R`.
50///
51/// # Type Parameters
52///
53/// * `T` - The type of the input value (consumed)
54/// * `R` - The type of the output value
55///
56/// # Author
57///
58/// Haixing Hu
59pub trait TransformerOnce<T, R> {
60 /// Transforms the input value, consuming both self and input
61 ///
62 /// # Parameters
63 ///
64 /// * `input` - The input value (consumed)
65 ///
66 /// # Returns
67 ///
68 /// The transformed output value
69 fn apply(self, input: T) -> R;
70
71 /// Converts to BoxTransformerOnce
72 ///
73 /// **⚠️ Consumes `self`**: The original transformer becomes unavailable
74 /// after calling this method.
75 ///
76 /// # Returns
77 ///
78 /// Returns `BoxTransformerOnce<T, R>`
79 ///
80 /// # Examples
81 ///
82 /// ```rust
83 /// use qubit_function::TransformerOnce;
84 ///
85 /// let double = |x: i32| x * 2;
86 /// let boxed = double.into_box();
87 /// assert_eq!(boxed.apply(21), 42);
88 /// ```
89 fn into_box(self) -> BoxTransformerOnce<T, R>
90 where
91 Self: Sized + 'static,
92 {
93 BoxTransformerOnce::new(move |input: T| self.apply(input))
94 }
95
96 /// Converts transformer to a closure
97 ///
98 /// **⚠️ Consumes `self`**: The original transformer becomes unavailable
99 /// after calling this method.
100 ///
101 /// # Returns
102 ///
103 /// Returns a closure that implements `FnOnce(T) -> R`
104 ///
105 /// # Examples
106 ///
107 /// ```rust
108 /// use qubit_function::TransformerOnce;
109 ///
110 /// let double = |x: i32| x * 2;
111 /// let func = double.into_fn();
112 /// assert_eq!(func(21), 42);
113 /// ```
114 fn into_fn(self) -> impl FnOnce(T) -> R
115 where
116 Self: Sized + 'static,
117 {
118 move |input: T| self.apply(input)
119 }
120
121 /// Converts to BoxTransformerOnce without consuming self
122 ///
123 /// **📌 Borrows `&self`**: The original transformer remains usable
124 /// after calling this method.
125 ///
126 /// # Default Implementation
127 ///
128 /// The default implementation creates a new `BoxTransformerOnce` that
129 /// captures a clone. Types implementing `Clone` can override this method
130 /// to provide more efficient conversions.
131 ///
132 /// # Returns
133 ///
134 /// Returns `BoxTransformerOnce<T, R>`
135 ///
136 /// # Examples
137 ///
138 /// ```rust
139 /// use qubit_function::TransformerOnce;
140 ///
141 /// let double = |x: i32| x * 2;
142 /// let boxed = double.to_box();
143 /// assert_eq!(boxed.apply(21), 42);
144 /// ```
145 fn to_box(&self) -> BoxTransformerOnce<T, R>
146 where
147 Self: Clone + 'static,
148 {
149 self.clone().into_box()
150 }
151
152 /// Converts transformer to a closure without consuming self
153 ///
154 /// **📌 Borrows `&self`**: The original transformer remains usable
155 /// after calling this method.
156 ///
157 /// # Default Implementation
158 ///
159 /// The default implementation creates a closure that captures a
160 /// clone of `self` and calls its `transform` method. Types can
161 /// override this method to provide more efficient conversions.
162 ///
163 /// # Returns
164 ///
165 /// Returns a closure that implements `FnOnce(T) -> R`
166 ///
167 /// # Examples
168 ///
169 /// ```rust
170 /// use qubit_function::TransformerOnce;
171 ///
172 /// let double = |x: i32| x * 2;
173 /// let func = double.to_fn();
174 /// assert_eq!(func(21), 42);
175 /// ```
176 fn to_fn(&self) -> impl FnOnce(T) -> R
177 where
178 Self: Clone + 'static,
179 {
180 self.clone().into_fn()
181 }
182}
183
184// ============================================================================
185// BoxTransformerOnce - Box<dyn FnOnce(T) -> R>
186// ============================================================================
187
188/// BoxTransformerOnce - consuming transformer wrapper based on
189/// `Box<dyn FnOnce>`
190///
191/// A transformer wrapper that provides single ownership with one-time use
192/// semantics. Consumes both self and the input value.
193///
194/// # Features
195///
196/// - **Based on**: `Box<dyn FnOnce(T) -> R>`
197/// - **Ownership**: Single ownership, cannot be cloned
198/// - **Reusability**: Can only be called once (consumes self and input)
199/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
200///
201/// # Author
202///
203/// Haixing Hu
204pub struct BoxTransformerOnce<T, R> {
205 function: Box<dyn FnOnce(T) -> R>,
206 name: Option<String>,
207}
208
209// Implement BoxTransformerOnce
210impl<T, R> BoxTransformerOnce<T, R> {
211 impl_transformer_common_methods!(
212 BoxTransformerOnce<T, R>,
213 (FnOnce(T) -> R + 'static),
214 |f| Box::new(f)
215 );
216
217 impl_box_transformer_methods!(
218 BoxTransformerOnce<T, R>,
219 BoxConditionalTransformerOnce,
220 TransformerOnce
221 );
222}
223
224// Implement TransformerOnce trait for BoxTransformerOnce
225impl<T, R> TransformerOnce<T, R> for BoxTransformerOnce<T, R> {
226 fn apply(self, input: T) -> R {
227 (self.function)(input)
228 }
229
230 impl_box_once_conversions!(
231 BoxTransformerOnce<T, R>,
232 TransformerOnce,
233 FnOnce(T) -> R
234 );
235}
236
237// Implement constant method for BoxTransformerOnce
238impl_transformer_constant_method!(BoxTransformerOnce<T, R>);
239
240// Use macro to generate Debug and Display implementations
241impl_transformer_debug_display!(BoxTransformerOnce<T, R>);
242
243// ============================================================================
244// Blanket implementation for standard FnOnce trait
245// ============================================================================
246
247// Implement TransformerOnce for all FnOnce(T) -> R using macro
248impl_closure_once_trait!(
249 TransformerOnce<T, R>,
250 apply,
251 BoxTransformerOnce,
252 FnOnce(input: T) -> R
253);
254
255// ============================================================================
256// FnTransformerOnceOps - Extension trait for FnOnce transformers
257// ============================================================================
258
259/// Extension trait for closures implementing `FnOnce(T) -> R`
260///
261/// Provides composition methods (`and_then`, `compose`, `when`) for one-time
262/// use closures and function pointers without requiring explicit wrapping in
263/// `BoxTransformerOnce`.
264///
265/// This trait is automatically implemented for all closures and function
266/// pointers that implement `FnOnce(T) -> R`.
267///
268/// # Design Rationale
269///
270/// While closures automatically implement `TransformerOnce<T, R>` through
271/// blanket implementation, they don't have access to instance methods like
272/// `and_then`, `compose`, and `when`. This extension trait provides those
273/// methods, returning `BoxTransformerOnce` for maximum flexibility.
274///
275/// # Examples
276///
277/// ## Chain composition with and_then
278///
279/// ```rust
280/// use qubit_function::{TransformerOnce, FnTransformerOnceOps};
281///
282/// let parse = |s: String| s.parse::<i32>().unwrap_or(0);
283/// let double = |x: i32| x * 2;
284///
285/// let composed = parse.and_then(double);
286/// assert_eq!(composed.apply("21".to_string()), 42);
287/// ```
288///
289/// ## Reverse composition with compose
290///
291/// ```rust
292/// use qubit_function::{TransformerOnce, FnTransformerOnceOps};
293///
294/// let double = |x: i32| x * 2;
295/// let to_string = |x: i32| x.to_string();
296///
297/// let composed = to_string.compose(double);
298/// assert_eq!(composed.apply(21), "42");
299/// ```
300///
301/// ## Conditional transformation with when
302///
303/// ```rust
304/// use qubit_function::{TransformerOnce, FnTransformerOnceOps};
305///
306/// let double = |x: i32| x * 2;
307/// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
308///
309/// assert_eq!(conditional.apply(5), 10);
310/// ```
311///
312/// # Author
313///
314/// Haixing Hu
315pub trait FnTransformerOnceOps<T, R>: FnOnce(T) -> R + Sized {
316 /// Chain composition - applies self first, then after
317 ///
318 /// Creates a new transformer that applies this transformer first, then
319 /// applies the after transformer to the result. Consumes self and returns
320 /// a `BoxTransformerOnce`.
321 ///
322 /// # Type Parameters
323 ///
324 /// * `S` - The output type of the after transformer
325 /// * `G` - The type of the after transformer (must implement
326 /// TransformerOnce<R, S>)
327 ///
328 /// # Parameters
329 ///
330 /// * `after` - The transformer to apply after self. **Note: This parameter
331 /// is passed by value and will transfer ownership.** Since this is a
332 /// `FnOnce` transformer, the parameter will be consumed. Can be:
333 /// - A closure: `|x: R| -> S`
334 /// - A function pointer: `fn(R) -> S`
335 /// - A `BoxTransformerOnce<R, S>`
336 /// - Any type implementing `TransformerOnce<R, S>`
337 ///
338 /// # Returns
339 ///
340 /// A new `BoxTransformerOnce<T, S>` representing the composition
341 ///
342 /// # Examples
343 ///
344 /// ```rust
345 /// use qubit_function::{TransformerOnce, FnTransformerOnceOps,
346 /// BoxTransformerOnce};
347 ///
348 /// let parse = |s: String| s.parse::<i32>().unwrap_or(0);
349 /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
350 ///
351 /// // double is moved and consumed
352 /// let composed = parse.and_then(double);
353 /// assert_eq!(composed.apply("21".to_string()), 42);
354 /// // double.apply(5); // Would not compile - moved
355 /// ```
356 fn and_then<S, G>(self, after: G) -> BoxTransformerOnce<T, S>
357 where
358 Self: 'static,
359 S: 'static,
360 G: TransformerOnce<R, S> + 'static,
361 T: 'static,
362 R: 'static,
363 {
364 BoxTransformerOnce::new(move |x: T| {
365 let intermediate = self(x);
366 after.apply(intermediate)
367 })
368 }
369
370 /// Creates a conditional transformer
371 ///
372 /// Returns a transformer that only executes when a predicate is satisfied.
373 /// You must call `or_else()` to provide an alternative transformer for when
374 /// the condition is not satisfied.
375 ///
376 /// # Parameters
377 ///
378 /// * `predicate` - The condition to check. **Note: This parameter is passed
379 /// by value and will transfer ownership.** If you need to preserve the
380 /// original predicate, clone it first (if it implements `Clone`). Can be:
381 /// - A closure: `|x: &T| -> bool`
382 /// - A function pointer: `fn(&T) -> bool`
383 /// - A `BoxPredicate<T>`
384 /// - An `RcPredicate<T>`
385 /// - An `ArcPredicate<T>`
386 /// - Any type implementing `Predicate<T>`
387 ///
388 /// # Returns
389 ///
390 /// Returns `BoxConditionalTransformerOnce<T, R>`
391 ///
392 /// # Examples
393 ///
394 /// ## Basic usage with or_else
395 ///
396 /// ```rust
397 /// use qubit_function::{TransformerOnce, FnTransformerOnceOps};
398 ///
399 /// let double = |x: i32| x * 2;
400 /// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
401 ///
402 /// assert_eq!(conditional.apply(5), 10);
403 /// ```
404 ///
405 /// ## Preserving predicate with clone
406 ///
407 /// ```rust
408 /// use qubit_function::{TransformerOnce, FnTransformerOnceOps,
409 /// RcPredicate};
410 ///
411 /// let double = |x: i32| x * 2;
412 /// let is_positive = RcPredicate::new(|x: &i32| *x > 0);
413 ///
414 /// // Clone to preserve original predicate
415 /// let conditional = double.when(is_positive.clone())
416 /// .or_else(|x: i32| -x);
417 ///
418 /// assert_eq!(conditional.apply(5), 10);
419 ///
420 /// // Original predicate still usable
421 /// assert!(is_positive.test(&3));
422 /// ```
423 fn when<P>(self, predicate: P) -> BoxConditionalTransformerOnce<T, R>
424 where
425 Self: 'static,
426 P: Predicate<T> + 'static,
427 T: 'static,
428 R: 'static,
429 {
430 BoxTransformerOnce::new(self).when(predicate)
431 }
432}
433
434/// Blanket implementation of FnTransformerOnceOps for all FnOnce closures
435///
436/// Automatically implements `FnTransformerOnceOps<T, R>` for any type that
437/// implements `FnOnce(T) -> R`.
438///
439/// # Author
440///
441/// Haixing Hu
442impl<T, R, F> FnTransformerOnceOps<T, R> for F where F: FnOnce(T) -> R {}
443
444// ============================================================================
445// UnaryOperatorOnce Trait - Marker trait for TransformerOnce<T, T>
446// ============================================================================
447
448/// UnaryOperatorOnce trait - marker trait for one-time use unary operators
449///
450/// A one-time use unary operator transforms a value of type `T` to another
451/// value of the same type `T`, consuming self in the process. This trait
452/// extends `TransformerOnce<T, T>` to provide semantic clarity for same-type
453/// transformations with consuming semantics. Equivalent to Java's
454/// `UnaryOperator<T>` but with FnOnce semantics.
455///
456/// # Automatic Implementation
457///
458/// This trait is automatically implemented for all types that implement
459/// `TransformerOnce<T, T>`, so you don't need to implement it manually.
460///
461/// # Type Parameters
462///
463/// * `T` - The type of both input and output values
464///
465/// # Examples
466///
467/// ## Using in generic constraints
468///
469/// ```rust
470/// use qubit_function::{UnaryOperatorOnce, TransformerOnce};
471///
472/// fn apply<T, O>(value: T, op: O) -> T
473/// where
474/// O: UnaryOperatorOnce<T>,
475/// {
476/// op.apply(value)
477/// }
478///
479/// let double = |x: i32| x * 2;
480/// assert_eq!(apply(21, double), 42);
481/// ```
482///
483/// # Author
484///
485/// Haixing Hu
486pub trait UnaryOperatorOnce<T>: TransformerOnce<T, T> {}
487
488/// Blanket implementation of UnaryOperatorOnce for all TransformerOnce<T, T>
489///
490/// This automatically implements `UnaryOperatorOnce<T>` for any type that
491/// implements `TransformerOnce<T, T>`.
492///
493/// # Author
494///
495/// Haixing Hu
496impl<F, T> UnaryOperatorOnce<T> for F
497where
498 F: TransformerOnce<T, T>,
499{
500 // empty
501}
502
503// ============================================================================
504// Type Aliases for UnaryOperatorOnce (TransformerOnce<T, T>)
505// ============================================================================
506
507/// Type alias for `BoxTransformerOnce<T, T>`
508///
509/// Represents a one-time use unary operator that transforms a value of type `T`
510/// to another value of the same type `T`. Equivalent to Java's `UnaryOperator<T>`
511/// with consuming semantics (FnOnce).
512///
513/// # Examples
514///
515/// ```rust
516/// use qubit_function::{BoxUnaryOperatorOnce, TransformerOnce};
517///
518/// let increment: BoxUnaryOperatorOnce<i32> = BoxUnaryOperatorOnce::new(|x| x + 1);
519/// assert_eq!(increment.apply(41), 42);
520/// ```
521///
522/// # Author
523///
524/// Haixing Hu
525pub type BoxUnaryOperatorOnce<T> = BoxTransformerOnce<T, T>;
526
527// ============================================================================
528// BoxConditionalTransformerOnce - Box-based Conditional Transformer
529// ============================================================================
530
531/// BoxConditionalTransformerOnce struct
532///
533/// A conditional consuming transformer that only executes when a predicate is
534/// satisfied. Uses `BoxTransformerOnce` and `BoxPredicate` for single
535/// ownership semantics.
536///
537/// This type is typically created by calling `BoxTransformerOnce::when()` and
538/// is designed to work with the `or_else()` method to create if-then-else
539/// logic.
540///
541/// # Features
542///
543/// - **Single Ownership**: Not cloneable, consumes `self` on use
544/// - **One-time Use**: Can only be called once
545/// - **Conditional Execution**: Only transforms when predicate returns `true`
546/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
547///
548/// # Examples
549///
550/// ## With or_else Branch
551///
552/// ```rust
553/// use qubit_function::{TransformerOnce, BoxTransformerOnce};
554///
555/// let double = BoxTransformerOnce::new(|x: i32| x * 2);
556/// let negate = BoxTransformerOnce::new(|x: i32| -x);
557/// let conditional = double.when(|x: &i32| *x > 0).or_else(negate);
558/// assert_eq!(conditional.apply(5), 10); // when branch executed
559///
560/// let double2 = BoxTransformerOnce::new(|x: i32| x * 2);
561/// let negate2 = BoxTransformerOnce::new(|x: i32| -x);
562/// let conditional2 = double2.when(|x: &i32| *x > 0).or_else(negate2);
563/// assert_eq!(conditional2.apply(-5), 5); // or_else branch executed
564/// ```
565///
566/// # Author
567///
568/// Haixing Hu
569pub struct BoxConditionalTransformerOnce<T, R> {
570 transformer: BoxTransformerOnce<T, R>,
571 predicate: BoxPredicate<T>,
572}
573
574// Implement BoxConditionalTransformerOnce
575impl_box_conditional_transformer!(
576 BoxConditionalTransformerOnce<T, R>,
577 BoxTransformerOnce,
578 TransformerOnce
579);
580
581// Use macro to generate Debug and Display implementations
582impl_conditional_transformer_debug_display!(BoxConditionalTransformerOnce<T, R>);