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