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
acceptmethod 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§
Sourcefn accept(self, first: &T, second: &U)
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 consumesecond- 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§
Sourcefn into_box(self) -> BoxBiConsumerOnce<T, U>where
Self: Sized + 'static,
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]);Sourcefn into_fn(self) -> impl FnOnce(&T, &U)where
Self: Sized + 'static,
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?
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}Sourcefn to_box(&self) -> BoxBiConsumerOnce<T, U>
fn to_box(&self) -> BoxBiConsumerOnce<T, U>
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]);Sourcefn to_fn(&self) -> impl FnOnce(&T, &U)
fn to_fn(&self) -> impl FnOnce(&T, &U)
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]);