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,
             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 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 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§

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 prism3_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, 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]);
Source

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?
examples/bi_consumer_once_demo.rs (line 159)
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}
Source

fn to_box(&self) -> BoxBiConsumerOnce<T, U>
where Self: Sized + Clone + 'static, T: 'static, U: '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 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]);
Source

fn to_fn(&self) -> impl FnOnce(&T, &U)
where Self: Sized + Clone + 'static, T: 'static, U: '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 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§

Source§

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

Source§

impl<T, U> BiConsumerOnce<T, U> for BoxConditionalBiConsumerOnce<T, U>
where T: 'static, U: 'static,

Source§

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

Implements BiConsumerOnce for all FnOnce(&T, &U)