Skip to main content

BiConsumerOnce

Trait BiConsumerOnce 

Source
pub trait BiConsumerOnce<T, U> {
    // Required method
    fn accept(self, first: &T, second: &U);

    // Provided methods
    fn into_box(self) -> BoxBiConsumerOnce<T, U>
       where Self: Sized + 'static { ... }
    fn into_fn(self) -> impl FnOnce(&T, &U)
       where Self: Sized + 'static { ... }
    fn to_box(&self) -> BoxBiConsumerOnce<T, U>
       where Self: Sized + Clone + 'static { ... }
    fn to_fn(&self) -> impl FnOnce(&T, &U)
       where Self: Sized + Clone + 'static { ... }
}
Expand description

BiConsumerOnce trait - Unified one-time bi-consumer interface

It is similar to the FnOnce(&T, &U) trait in the standard library.

Defines core behavior for all one-time bi-consumer types. Similar to a bi-consumer implementing FnOnce(&T, &U), performs operations accepting two value references but returning no result (side effects only), consuming itself in the process.

§Automatic Implementations

  • All closures implementing FnOnce(&T, &U)
  • BoxBiConsumerOnce<T, U>

§Features

  • Unified Interface: All bi-consumer types share the same accept method signature
  • Automatic Implementation: Closures automatically implement this trait with zero overhead
  • Type Conversions: Can convert to BoxBiConsumerOnce
  • Generic Programming: Write functions accepting any one-time bi-consumer type

§Examples

use qubit_function::{BiConsumerOnce, BoxBiConsumerOnce};
use std::sync::{Arc, Mutex};

fn apply_consumer<C: BiConsumerOnce<i32, i32>>(
    consumer: C,
    a: &i32,
    b: &i32
) {
    consumer.accept(a, b);
}

let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let box_con = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
    l.lock().expect("mutex should not be poisoned").push(*x + *y);
});
apply_consumer(box_con, &5, &3);
assert_eq!(*log.lock().expect("mutex should not be poisoned"), vec![8]);

Required Methods§

Source

fn accept(self, first: &T, second: &U)

Performs the one-time consumption operation

Executes an operation on the given two references. The operation typically reads input values or produces side effects, but does not modify the input values themselves. Consumes self.

§Parameters
  • first - Reference to the first value to consume
  • second - Reference to the second value to consume
§Examples
use qubit_function::{BiConsumerOnce, BoxBiConsumerOnce};

let consumer = BoxBiConsumerOnce::new(|x: &i32, y: &i32| {
    println!("Sum: {}", x + y);
});
consumer.accept(&5, &3);

Provided Methods§

Source

fn into_box(self) -> BoxBiConsumerOnce<T, U>
where Self: Sized + 'static,

Converts to BoxBiConsumerOnce

⚠️ Consumes self: Original consumer becomes unavailable after calling this method.

§Returns

Returns the wrapped BoxBiConsumerOnce<T, U>

§Examples
use qubit_function::BiConsumerOnce;
use std::sync::{Arc, Mutex};

let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32, y: &i32| {
    l.lock().expect("mutex should not be poisoned").push(*x + *y);
};
let box_consumer = closure.into_box();
box_consumer.accept(&5, &3);
assert_eq!(*log.lock().expect("mutex should not be poisoned"), vec![8]);
Source

fn into_fn(self) -> impl FnOnce(&T, &U)
where Self: Sized + 'static,

Converts to a closure

⚠️ Consumes self: Original consumer becomes unavailable after calling this method.

Converts the one-time bi-consumer to a closure usable with standard library methods requiring FnOnce.

§Returns

Returns a closure implementing FnOnce(&T, &U)

Examples found in repository?
examples/consumers/bi_consumer_once_demo.rs (line 203)
25fn main() {
26    println!("=== BiConsumerOnce Demo ===\n");
27
28    // 1. Basic usage
29    println!("1. Basic usage:");
30    let log = Arc::new(Mutex::new(Vec::new()));
31    let l = log.clone();
32    let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
33        l.lock()
34            .expect("mutex should not be poisoned")
35            .push(*x + *y);
36        println!("  Sum: {}", x + y);
37    });
38    consumer.accept(&10, &5);
39    println!(
40        "  Log: {:?}\n",
41        *log.lock().expect("mutex should not be poisoned")
42    );
43
44    // 2. Method chaining
45    println!("2. Method chaining:");
46    let log = Arc::new(Mutex::new(Vec::new()));
47    let l1 = log.clone();
48    let l2 = log.clone();
49    let chained = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
50        l1.lock()
51            .expect("mutex should not be poisoned")
52            .push(*x + *y);
53        println!("  First: sum={}", x + y);
54    })
55    .and_then(move |x: &i32, y: &i32| {
56        l2.lock()
57            .expect("mutex should not be poisoned")
58            .push(*x * *y);
59        println!("  Second: product={}", x * y);
60    });
61    chained.accept(&5, &3);
62    println!(
63        "  Log: {:?}\n",
64        *log.lock().expect("mutex should not be poisoned")
65    );
66
67    // 3. Conditional execution - true case
68    println!("3. Conditional execution - true case:");
69    let log = Arc::new(Mutex::new(Vec::new()));
70    let l = log.clone();
71    let conditional = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
72        l.lock()
73            .expect("mutex should not be poisoned")
74            .push(*x + *y);
75    })
76    .when(|x: &i32, y: &i32| *x > 0 && *y > 0);
77    conditional.accept(&5, &3);
78    println!(
79        "  Positive values: {:?}\n",
80        *log.lock().expect("mutex should not be poisoned")
81    );
82
83    // 4. Conditional execution - false case
84    println!("4. Conditional execution - false case:");
85    let log = Arc::new(Mutex::new(Vec::new()));
86    let l = log.clone();
87    let conditional = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
88        l.lock()
89            .expect("mutex should not be poisoned")
90            .push(*x + *y);
91    })
92    .when(|x: &i32, y: &i32| *x > 0 && *y > 0);
93    conditional.accept(&-5, &3);
94    println!(
95        "  Negative value (unchanged): {:?}\n",
96        *log.lock().expect("mutex should not be poisoned")
97    );
98
99    // 5. Conditional branching
100    println!("5. Conditional branching:");
101    let log = Arc::new(Mutex::new(Vec::new()));
102    let l1 = log.clone();
103    let l2 = log.clone();
104    let branch = BoxBiConsumerOnce::new(move |x: &i32, _y: &i32| {
105        l1.lock().expect("mutex should not be poisoned").push(*x);
106    })
107    .when(|x: &i32, y: &i32| *x > *y)
108    .or_else(move |_x: &i32, y: &i32| {
109        l2.lock().expect("mutex should not be poisoned").push(*y);
110    });
111    branch.accept(&15, &10);
112    println!(
113        "  When x > y: {:?}\n",
114        *log.lock().expect("mutex should not be poisoned")
115    );
116
117    // 6. Working with closures directly
118    println!("6. Working with closures directly:");
119    let log = Arc::new(Mutex::new(Vec::new()));
120    let l = log.clone();
121    let closure = move |x: &i32, y: &i32| {
122        l.lock()
123            .expect("mutex should not be poisoned")
124            .push(*x + *y);
125        println!("  Processed: {}", x + y);
126    };
127    closure.accept(&10, &20);
128    println!(
129        "  Log: {:?}\n",
130        *log.lock().expect("mutex should not be poisoned")
131    );
132
133    // 7. Moving captured values
134    println!("7. Moving captured values:");
135    let data = vec![1, 2, 3, 4, 5];
136    let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
137        println!("  x={}, y={}", x, y);
138        println!("  Captured data: {:?}", data);
139        println!("  Data sum: {}", data.iter().sum::<i32>());
140    });
141    consumer.accept(&5, &3);
142    // data is no longer available here
143    println!();
144
145    // 8. Initialization callback
146    println!("8. Initialization callback:");
147    let log = Arc::new(Mutex::new(Vec::new()));
148    let l = log.clone();
149    let init_callback = BoxBiConsumerOnce::new(move |width: &i32, height: &i32| {
150        println!("  Initializing with dimensions: {}x{}", width, height);
151        l.lock()
152            .expect("mutex should not be poisoned")
153            .push(*width * *height);
154    });
155    init_callback.accept(&800, &600);
156    println!(
157        "  Areas: {:?}\n",
158        *log.lock().expect("mutex should not be poisoned")
159    );
160
161    // 9. Cleanup callback
162    println!("9. Cleanup callback:");
163    let cleanup = BoxBiConsumerOnce::new(|count: &i32, total: &i32| {
164        println!("  Cleanup: processed {} out of {} items", count, total);
165        println!(
166            "  Success rate: {:.1}%",
167            (*count as f64 / *total as f64) * 100.0
168        );
169    });
170    cleanup.accept(&85, &100);
171    println!();
172
173    // 10. Name support
174    println!("10. Name support:");
175    let mut named_consumer = BoxBiConsumerOnce::<i32, i32>::noop();
176    println!("  Initial name: {:?}", named_consumer.name());
177
178    named_consumer.set_name("init_callback");
179    println!("  After setting name: {:?}", named_consumer.name());
180    println!("  Display: {}", named_consumer);
181    named_consumer.accept(&1, &2);
182    println!();
183
184    // 11. Print helpers
185    println!("11. Print helpers:");
186    let print = BoxBiConsumerOnce::new(|x: &i32, y: &i32| println!("{}, {}", x, y));
187    print.accept(&42, &10);
188
189    let print_with =
190        BoxBiConsumerOnce::new(|x: &i32, y: &i32| println!("Dimensions: {}, {}", x, y));
191    print_with.accept(&800, &600);
192    println!();
193
194    // 12. Converting to function
195    println!("12. Converting to function:");
196    let log = Arc::new(Mutex::new(Vec::new()));
197    let l = log.clone();
198    let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
199        l.lock()
200            .expect("mutex should not be poisoned")
201            .push(*x + *y);
202    });
203    let func = consumer.into_fn();
204    func(&7, &3);
205    println!(
206        "  Log: {:?}\n",
207        *log.lock().expect("mutex should not be poisoned")
208    );
209
210    println!("=== Demo Complete ===");
211}
Source

fn to_box(&self) -> BoxBiConsumerOnce<T, U>
where Self: Sized + Clone + 'static,

Convert to BoxBiConsumerOnce without consuming self

⚠️ Requires Clone: This method requires Self to implement Clone. Clones the current bi-consumer and then converts the clone to a BoxBiConsumerOnce.

§Returns

Returns the wrapped BoxBiConsumerOnce<T, U>

§Examples
use qubit_function::BiConsumerOnce;
use std::sync::{Arc, Mutex};

let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32, y: &i32| {
    l.lock().expect("mutex should not be poisoned").push(*x + *y);
};
let box_consumer = closure.to_box();
box_consumer.accept(&5, &3);
assert_eq!(*log.lock().expect("mutex should not be poisoned"), vec![8]);
Source

fn to_fn(&self) -> impl FnOnce(&T, &U)
where Self: Sized + Clone + 'static,

Convert to closure without consuming self

⚠️ Requires Clone: This method requires Self to implement Clone. Clones the current bi-consumer and then converts the clone to a closure.

§Returns

Returns a closure implementing FnOnce(&T, &U)

§Examples
use qubit_function::BiConsumerOnce;
use std::sync::{Arc, Mutex};

let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32, y: &i32| {
    l.lock().expect("mutex should not be poisoned").push(*x + *y);
};
let func = closure.to_fn();
func(&5, &3);
assert_eq!(*log.lock().expect("mutex should not be poisoned"), vec![8]);

Implementors§

Source§

impl<F, T, U> BiConsumerOnce<T, U> for F
where F: FnOnce(&T, &U),

Source§

impl<T, U> BiConsumerOnce<T, U> for BoxBiConsumerOnce<T, U>

Source§

impl<T, U> BiConsumerOnce<T, U> for BoxConditionalBiConsumerOnce<T, U>