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,
T: 'static,
U: 'static { ... }
fn into_fn(self) -> impl FnOnce(&T, &U)
where Self: Sized + 'static,
T: 'static,
U: 'static { ... }
fn to_box(&self) -> BoxBiConsumerOnce<T, U>
where Self: Sized + Clone + 'static,
T: 'static,
U: 'static { ... }
fn to_fn(&self) -> impl FnOnce(&T, &U)
where Self: Sized + Clone + 'static,
T: 'static,
U: 'static { ... }
}Expand description
BiConsumerOnce trait - Unified one-time bi-consumer interface
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 prism3_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]);§Author
Haixing Hu
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 prism3_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,
T: 'static,
U: 'static,
fn into_box(self) -> BoxBiConsumerOnce<T, U>where
Self: Sized + 'static,
T: 'static,
U: 'static,
Converts to BoxBiConsumerOnce
⚠️ Consumes self: Original consumer becomes unavailable after
calling this method.
§Returns
Returns the wrapped BoxBiConsumerOnce<T, U>
§Examples
use prism3_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,
T: 'static,
U: 'static,
fn into_fn(self) -> impl FnOnce(&T, &U)where
Self: Sized + 'static,
T: 'static,
U: '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?
18fn main() {
19 println!("=== BiConsumerOnce Demo ===\n");
20
21 // 1. Basic usage
22 println!("1. Basic usage:");
23 let log = Arc::new(Mutex::new(Vec::new()));
24 let l = log.clone();
25 let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
26 l.lock().unwrap().push(*x + *y);
27 println!(" Sum: {}", x + y);
28 });
29 consumer.accept(&10, &5);
30 println!(" Log: {:?}\n", *log.lock().unwrap());
31
32 // 2. Method chaining
33 println!("2. Method chaining:");
34 let log = Arc::new(Mutex::new(Vec::new()));
35 let l1 = log.clone();
36 let l2 = log.clone();
37 let chained = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
38 l1.lock().unwrap().push(*x + *y);
39 println!(" First: sum={}", x + y);
40 })
41 .and_then(move |x: &i32, y: &i32| {
42 l2.lock().unwrap().push(*x * *y);
43 println!(" Second: product={}", x * y);
44 });
45 chained.accept(&5, &3);
46 println!(" Log: {:?}\n", *log.lock().unwrap());
47
48 // 3. Conditional execution - true case
49 println!("3. Conditional execution - true case:");
50 let log = Arc::new(Mutex::new(Vec::new()));
51 let l = log.clone();
52 let conditional = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
53 l.lock().unwrap().push(*x + *y);
54 })
55 .when(|x: &i32, y: &i32| *x > 0 && *y > 0);
56 conditional.accept(&5, &3);
57 println!(" Positive values: {:?}\n", *log.lock().unwrap());
58
59 // 4. Conditional execution - false case
60 println!("4. Conditional execution - false case:");
61 let log = Arc::new(Mutex::new(Vec::new()));
62 let l = log.clone();
63 let conditional = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
64 l.lock().unwrap().push(*x + *y);
65 })
66 .when(|x: &i32, y: &i32| *x > 0 && *y > 0);
67 conditional.accept(&-5, &3);
68 println!(" Negative value (unchanged): {:?}\n", *log.lock().unwrap());
69
70 // 5. Conditional branching
71 println!("5. Conditional branching:");
72 let log = Arc::new(Mutex::new(Vec::new()));
73 let l1 = log.clone();
74 let l2 = log.clone();
75 let branch = BoxBiConsumerOnce::new(move |x: &i32, _y: &i32| {
76 l1.lock().unwrap().push(*x);
77 })
78 .when(|x: &i32, y: &i32| *x > *y)
79 .or_else(move |_x: &i32, y: &i32| {
80 l2.lock().unwrap().push(*y);
81 });
82 branch.accept(&15, &10);
83 println!(" When x > y: {:?}\n", *log.lock().unwrap());
84
85 // 6. Working with closures directly
86 println!("6. Working with closures directly:");
87 let log = Arc::new(Mutex::new(Vec::new()));
88 let l = log.clone();
89 let closure = move |x: &i32, y: &i32| {
90 l.lock().unwrap().push(*x + *y);
91 println!(" Processed: {}", x + y);
92 };
93 closure.accept(&10, &20);
94 println!(" Log: {:?}\n", *log.lock().unwrap());
95
96 // 7. Moving captured values
97 println!("7. Moving captured values:");
98 let data = vec![1, 2, 3, 4, 5];
99 let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
100 println!(" x={}, y={}", x, y);
101 println!(" Captured data: {:?}", data);
102 println!(" Data sum: {}", data.iter().sum::<i32>());
103 });
104 consumer.accept(&5, &3);
105 // data is no longer available here
106 println!();
107
108 // 8. Initialization callback
109 println!("8. Initialization callback:");
110 let log = Arc::new(Mutex::new(Vec::new()));
111 let l = log.clone();
112 let init_callback = BoxBiConsumerOnce::new(move |width: &i32, height: &i32| {
113 println!(" Initializing with dimensions: {}x{}", width, height);
114 l.lock().unwrap().push(*width * *height);
115 });
116 init_callback.accept(&800, &600);
117 println!(" Areas: {:?}\n", *log.lock().unwrap());
118
119 // 9. Cleanup callback
120 println!("9. Cleanup callback:");
121 let cleanup = BoxBiConsumerOnce::new(|count: &i32, total: &i32| {
122 println!(" Cleanup: processed {} out of {} items", count, total);
123 println!(
124 " Success rate: {:.1}%",
125 (*count as f64 / *total as f64) * 100.0
126 );
127 });
128 cleanup.accept(&85, &100);
129 println!();
130
131 // 10. Name support
132 println!("10. Name support:");
133 let mut named_consumer = BoxBiConsumerOnce::<i32, i32>::noop();
134 println!(" Initial name: {:?}", named_consumer.name());
135
136 named_consumer.set_name("init_callback");
137 println!(" After setting name: {:?}", named_consumer.name());
138 println!(" Display: {}", named_consumer);
139 named_consumer.accept(&1, &2);
140 println!();
141
142 // 11. Print helpers
143 println!("11. Print helpers:");
144 let print = BoxBiConsumerOnce::new(|x: &i32, y: &i32| println!("{}, {}", x, y));
145 print.accept(&42, &10);
146
147 let print_with =
148 BoxBiConsumerOnce::new(|x: &i32, y: &i32| println!("Dimensions: {}, {}", x, y));
149 print_with.accept(&800, &600);
150 println!();
151
152 // 12. Converting to function
153 println!("12. Converting to function:");
154 let log = Arc::new(Mutex::new(Vec::new()));
155 let l = log.clone();
156 let consumer = BoxBiConsumerOnce::new(move |x: &i32, y: &i32| {
157 l.lock().unwrap().push(*x + *y);
158 });
159 let func = consumer.into_fn();
160 func(&7, &3);
161 println!(" Log: {:?}\n", *log.lock().unwrap());
162
163 println!("=== Demo Complete ===");
164}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 prism3_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 prism3_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]);Implementors§
impl<T, U> BiConsumerOnce<T, U> for BoxBiConsumerOnce<T, U>
impl<T, U> BiConsumerOnce<T, U> for BoxConditionalBiConsumerOnce<T, U>where
T: 'static,
U: 'static,
impl<T, U, F> BiConsumerOnce<T, U> for F
Implements BiConsumerOnce for all FnOnce(&T, &U)