Skip to main content

qubit_function/consumers/consumer/
fn_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 `FnConsumerOps` 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 consumer composition methods for closures
22///
23/// Provides `and_then` and other composition methods for all closures
24/// implementing `Fn(&T)`, allowing closures to directly chain methods without
25/// explicit wrapper types.
26///
27/// # Features
28///
29/// - **Natural Syntax**: Chain operations directly on closures
30/// - **Returns BoxConsumer**: Combined results can continue chaining
31/// - **Zero Cost**: No overhead when composing closures
32/// - **Auto-implementation**: All `Fn(&T)` closures automatically get these
33///   methods
34///
35/// # Examples
36///
37/// ```rust
38/// use qubit_function::{Consumer, FnConsumerOps};
39///
40/// let chained = (|x: &i32| {
41///     println!("First: {}", x);
42/// }).and_then(|x: &i32| {
43///     println!("Second: {}", x);
44/// });
45/// chained.accept(&5);
46/// ```
47///
48pub trait FnConsumerOps<T>: Fn(&T) + Sized {
49    /// Sequentially chain another non-mutating consumer
50    ///
51    /// Returns a new consumer that executes the current operation first, then the
52    /// next operation. Consumes the current closure and returns
53    /// `BoxConsumer<T>`.
54    ///
55    /// # Type Parameters
56    ///
57    /// * `C` - Type of the next consumer
58    ///
59    /// # Parameters
60    ///
61    /// * `next` - Consumer to execute after the current operation
62    ///
63    /// # Returns
64    ///
65    /// Returns a combined `BoxConsumer<T>`
66    ///
67    /// # Examples
68    ///
69    /// ```rust
70    /// use qubit_function::{Consumer, FnConsumerOps};
71    ///
72    /// let chained = (|x: &i32| {
73    ///     println!("First: {}", x);
74    /// }).and_then(|x: &i32| {
75    ///     println!("Second: {}", x);
76    /// }).and_then(|x: &i32| println!("Third: {}", x));
77    ///
78    /// chained.accept(&5);
79    /// ```
80    fn and_then<C>(self, next: C) -> BoxConsumer<T>
81    where
82        Self: 'static,
83        C: Consumer<T> + 'static,
84        T: 'static,
85    {
86        let first = self;
87        let second = next;
88        BoxConsumer::new(move |t| {
89            first(t);
90            second.accept(t);
91        })
92    }
93}
94
95/// Implement FnConsumerOps for all closure types
96impl<T, F> FnConsumerOps<T> for F where F: Fn(&T) {}