qubit_function/consumers/bi_consumer/fn_bi_consumer_ops.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// qubit-style: allow explicit-imports
11//! Defines the `FnBiConsumerOps` public type.
12
13#![allow(unused_imports)]
14
15use super::*;
16
17// =======================================================================
18// 6. Provide extension methods for closures
19// =======================================================================
20
21/// Extension trait providing non-mutating bi-consumer composition methods for
22/// closures
23///
24/// Provides `and_then` and other composition methods for all closures
25/// implementing `Fn(&T, &U)`, enabling direct method chaining on closures
26/// without explicit wrapper types.
27///
28/// # Features
29///
30/// - **Natural Syntax**: Chain operations directly on closures
31/// - **Returns BoxBiConsumer**: Composition results can be
32/// further chained
33/// - **Zero Cost**: No overhead when composing closures
34/// - **Automatic Implementation**: All `Fn(&T, &U)` closures get these
35/// methods automatically
36///
37/// # Examples
38///
39/// ```rust
40/// use qubit_function::{BiConsumer, FnBiConsumerOps};
41///
42/// let chained = (|x: &i32, y: &i32| {
43/// println!("First: {}, {}", x, y);
44/// }).and_then(|x: &i32, y: &i32| {
45/// println!("Second: sum = {}", x + y);
46/// });
47/// chained.accept(&5, &3);
48/// ```
49///
50pub trait FnBiConsumerOps<T, U>: Fn(&T, &U) + Sized {
51 /// Chains another non-mutating bi-consumer in sequence
52 ///
53 /// Returns a new consumer executing the current operation first, then
54 /// the next operation. Consumes the current closure and returns
55 /// `BoxBiConsumer<T, U>`.
56 ///
57 /// # Type Parameters
58 ///
59 /// * `C` - The type of the next consumer
60 ///
61 /// # Parameters
62 ///
63 /// * `next` - The consumer to execute after the current operation
64 ///
65 /// # Returns
66 ///
67 /// Returns the composed `BoxBiConsumer<T, U>`
68 ///
69 /// # Examples
70 ///
71 /// ```rust
72 /// use qubit_function::{BiConsumer, FnBiConsumerOps};
73 ///
74 /// let chained = (|x: &i32, y: &i32| {
75 /// println!("First: {}, {}", x, y);
76 /// }).and_then(|x: &i32, y: &i32| {
77 /// println!("Second: sum = {}", x + y);
78 /// }).and_then(|x: &i32, y: &i32| {
79 /// println!("Third: product = {}", x * y);
80 /// });
81 ///
82 /// chained.accept(&5, &3);
83 /// ```
84 fn and_then<C>(self, next: C) -> BoxBiConsumer<T, U>
85 where
86 Self: 'static,
87 C: BiConsumer<T, U> + 'static,
88 T: 'static,
89 U: 'static,
90 {
91 let first = self;
92 let second = next;
93 BoxBiConsumer::new(move |t, u| {
94 first(t, u);
95 second.accept(t, u);
96 })
97 }
98}
99
100/// Implements FnBiConsumerOps for all closure types
101impl<T, U, F> FnBiConsumerOps<T, U> for F where F: Fn(&T, &U) {}