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().unwrap().push(*x + *y);
});
apply_consumer(box_con, &5, &3);
assert_eq!(*log.lock().unwrap(), 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().unwrap().push(*x + *y);
};
let box_consumer = closure.into_box();
box_consumer.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), 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().unwrap().push(*x + *y);
34 println!(" Sum: {}", x + y);
35 });
36 consumer.accept(&10, &5);
37 println!(" Log: {:?}\n", *log.lock().unwrap());
38
39 // 2. Method chaining
40 println!("2. Method chaining:");
41 let log = Arc::new(Mutex::new(Vec::new()));
42 let l1 = log.clone();
43 let l2 = log.clone();
44 let chained = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
45 l1.lock().unwrap().push(*x + *y);
46 println!(" First: sum={}", x + y);
47 })
48 .and_then(move |x: &i32, y: &i32| {
49 l2.lock().unwrap().push(*x * *y);
50 println!(" Second: product={}", x * y);
51 });
52 chained.accept(&5, &3);
53 println!(" Log: {:?}\n", *log.lock().unwrap());
54
55 // 3. Conditional execution - true case
56 println!("3. Conditional execution - true case:");
57 let log = Arc::new(Mutex::new(Vec::new()));
58 let l = log.clone();
59 let conditional = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
60 l.lock().unwrap().push(*x + *y);
61 })
62 .when(|x: &i32, y: &i32| *x > 0 && *y > 0);
63 conditional.accept(&5, &3);
64 println!(" Positive values: {:?}\n", *log.lock().unwrap());
65
66 // 4. Conditional execution - false case
67 println!("4. Conditional execution - false case:");
68 let log = Arc::new(Mutex::new(Vec::new()));
69 let l = log.clone();
70 let conditional = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
71 l.lock().unwrap().push(*x + *y);
72 })
73 .when(|x: &i32, y: &i32| *x > 0 && *y > 0);
74 conditional.accept(&-5, &3);
75 println!(" Negative value (unchanged): {:?}\n", *log.lock().unwrap());
76
77 // 5. Conditional branching
78 println!("5. Conditional branching:");
79 let log = Arc::new(Mutex::new(Vec::new()));
80 let l1 = log.clone();
81 let l2 = log.clone();
82 let branch = BoxBiConsumerOnce::new(move |x: &i32, _y: &i32| {
83 l1.lock().unwrap().push(*x);
84 })
85 .when(|x: &i32, y: &i32| *x > *y)
86 .or_else(move |_x: &i32, y: &i32| {
87 l2.lock().unwrap().push(*y);
88 });
89 branch.accept(&15, &10);
90 println!(" When x > y: {:?}\n", *log.lock().unwrap());
91
92 // 6. Working with closures directly
93 println!("6. Working with closures directly:");
94 let log = Arc::new(Mutex::new(Vec::new()));
95 let l = log.clone();
96 let closure = move |x: &i32, y: &i32| {
97 l.lock().unwrap().push(*x + *y);
98 println!(" Processed: {}", x + y);
99 };
100 closure.accept(&10, &20);
101 println!(" Log: {:?}\n", *log.lock().unwrap());
102
103 // 7. Moving captured values
104 println!("7. Moving captured values:");
105 let data = vec![1, 2, 3, 4, 5];
106 let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
107 println!(" x={}, y={}", x, y);
108 println!(" Captured data: {:?}", data);
109 println!(" Data sum: {}", data.iter().sum::<i32>());
110 });
111 consumer.accept(&5, &3);
112 // data is no longer available here
113 println!();
114
115 // 8. Initialization callback
116 println!("8. Initialization callback:");
117 let log = Arc::new(Mutex::new(Vec::new()));
118 let l = log.clone();
119 let init_callback = BoxBiConsumerOnce::new(move |width: &i32, height: &i32| {
120 println!(" Initializing with dimensions: {}x{}", width, height);
121 l.lock().unwrap().push(*width * *height);
122 });
123 init_callback.accept(&800, &600);
124 println!(" Areas: {:?}\n", *log.lock().unwrap());
125
126 // 9. Cleanup callback
127 println!("9. Cleanup callback:");
128 let cleanup = BoxBiConsumerOnce::new(|count: &i32, total: &i32| {
129 println!(" Cleanup: processed {} out of {} items", count, total);
130 println!(
131 " Success rate: {:.1}%",
132 (*count as f64 / *total as f64) * 100.0
133 );
134 });
135 cleanup.accept(&85, &100);
136 println!();
137
138 // 10. Name support
139 println!("10. Name support:");
140 let mut named_consumer = BoxBiConsumerOnce::<i32, i32>::noop();
141 println!(" Initial name: {:?}", named_consumer.name());
142
143 named_consumer.set_name("init_callback");
144 println!(" After setting name: {:?}", named_consumer.name());
145 println!(" Display: {}", named_consumer);
146 named_consumer.accept(&1, &2);
147 println!();
148
149 // 11. Print helpers
150 println!("11. Print helpers:");
151 let print = BoxBiConsumerOnce::new(|x: &i32, y: &i32| println!("{}, {}", x, y));
152 print.accept(&42, &10);
153
154 let print_with =
155 BoxBiConsumerOnce::new(|x: &i32, y: &i32| println!("Dimensions: {}, {}", x, y));
156 print_with.accept(&800, &600);
157 println!();
158
159 // 12. Converting to function
160 println!("12. Converting to function:");
161 let log = Arc::new(Mutex::new(Vec::new()));
162 let l = log.clone();
163 let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
164 l.lock().unwrap().push(*x + *y);
165 });
166 let func = consumer.into_fn();
167 func(&7, &3);
168 println!(" Log: {:?}\n", *log.lock().unwrap());
169
170 println!("=== Demo Complete ===");
171}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().unwrap().push(*x + *y);
};
let box_consumer = closure.to_box();
box_consumer.accept(&5, &3);
assert_eq!(*log.lock().unwrap(), 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().unwrap().push(*x + *y);
};
let func = closure.to_fn();
func(&5, &3);
assert_eq!(*log.lock().unwrap(), vec![8]);