Skip to main content

ConsumerOnce

Trait ConsumerOnce 

Source
pub trait ConsumerOnce<T> {
    // Required method
    fn accept(self, value: &T);

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

ConsumerOnce trait - Unified one-time consumer interface

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

Defines the core behavior of all one-time consumer types. Similar to consumers implementing FnOnce(&T), executes operations that accept a value reference but return no result (only side effects), consuming itself in the process.

§Automatic Implementation

  • All closures implementing FnOnce(&T)
  • BoxConsumerOnce<T>

§Features

  • Unified Interface: All consumer types share the same accept method signature
  • Automatic Implementation: Closures automatically implement this trait with zero overhead
  • Type Conversion: Can be converted to BoxConsumerOnce
  • Generic Programming: Write functions that work with any one-time consumer type

§Examples

use qubit_function::{ConsumerOnce, BoxConsumerOnce};
use std::sync::{Arc, Mutex};

fn apply_consumer<C: ConsumerOnce<i32>>(consumer: C, value: &i32) {
    consumer.accept(value);
}

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

Required Methods§

Source

fn accept(self, value: &T)

Execute one-time consumption operation

Executes an operation on the given reference. The operation typically reads the input value or produces side effects, but does not modify the input value itself. Consumes self.

§Parameters
  • value - Reference to the value to be consumed
§Examples
use qubit_function::{ConsumerOnce, BoxConsumerOnce};

let consumer = BoxConsumerOnce::new(|x: &i32| println!("{}", x));
consumer.accept(&5);

Provided Methods§

Source

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

Convert to BoxConsumerOnce

⚠️ Consumes self: The original consumer will be unavailable after calling this method.

§Default Implementation

The default implementation wraps self in a BoxConsumerOnce by calling accept on the consumer. Types can override this method to provide more efficient conversions.

§Returns

Returns the wrapped BoxConsumerOnce<T>

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

let log = Arc::new(Mutex::new(Vec::new()));
let l = log.clone();
let closure = move |x: &i32| {
    l.lock().expect("mutex should not be poisoned").push(*x);
};
let box_consumer = closure.into_box();
box_consumer.accept(&5);
assert_eq!(*log.lock().expect("mutex should not be poisoned"), vec![5]);
Examples found in repository?
examples/consumers/consumer_once_demo.rs (line 170)
24fn main() {
25    println!("=== ConsumerOnce Demo ===\n");
26
27    // 1. BoxConsumerOnce - Single ownership, one-time use
28    println!("1. BoxConsumerOnce - Single ownership");
29    {
30        let log = Arc::new(Mutex::new(Vec::new()));
31        let l = log.clone();
32        let consumer = BoxConsumerOnce::new(move |x: &i32| {
33            l.lock().expect("mutex should not be poisoned").push(*x);
34            println!("  BoxConsumerOnce consumed: {}", x);
35        });
36        consumer.accept(&42);
37        println!(
38            "  Log: {:?}\n",
39            *log.lock().expect("mutex should not be poisoned")
40        );
41    }
42
43    // 2. BoxConsumerOnce - Method chaining
44    println!("2. BoxConsumerOnce - Method chaining");
45    {
46        let log = Arc::new(Mutex::new(Vec::new()));
47        let l1 = log.clone();
48        let l2 = log.clone();
49        let l3 = log.clone();
50        let chained = BoxConsumerOnce::new(move |x: &i32| {
51            l1.lock()
52                .expect("mutex should not be poisoned")
53                .push(*x * 2);
54            println!("  Step 1: {} * 2 = {}", x, x * 2);
55        })
56        .and_then(move |x: &i32| {
57            l2.lock()
58                .expect("mutex should not be poisoned")
59                .push(*x + 10);
60            println!("  Step 2: {} + 10 = {}", x, x + 10);
61        })
62        .and_then(move |x: &i32| {
63            l3.lock()
64                .expect("mutex should not be poisoned")
65                .push(*x - 1);
66            println!("  Step 3: {} - 1 = {}", x, x - 1);
67        });
68        chained.accept(&5);
69        println!(
70            "  Log: {:?}\n",
71            *log.lock().expect("mutex should not be poisoned")
72        );
73    }
74
75    // 3. BoxConsumerOnce - Factory methods
76    println!("3. BoxConsumerOnce - Factory methods");
77    {
78        // No-op consumer
79        let noop = BoxConsumerOnce::<i32>::noop();
80        noop.accept(&42);
81        println!("  No-op consumer executed (no output)");
82
83        // Print consumer
84        print!("  Print consumer: ");
85        let print = BoxConsumerOnce::new(|x: &i32| println!("{}", x));
86        print.accept(&42);
87
88        // Print with prefix
89        print!("  Print with prefix: ");
90        let print_with = BoxConsumerOnce::new(|x: &i32| println!("Value: {}", x));
91        print_with.accept(&42);
92
93        // Conditional consumer
94        let log = Arc::new(Mutex::new(Vec::new()));
95        let l = log.clone();
96        let conditional = BoxConsumerOnce::new(move |x: &i32| {
97            l.lock().expect("mutex should not be poisoned").push(*x * 2);
98        })
99        .when(|x: &i32| *x > 0);
100        conditional.accept(&5);
101        println!(
102            "  Conditional (positive): {:?}",
103            *log.lock().expect("mutex should not be poisoned")
104        );
105
106        let log = Arc::new(Mutex::new(Vec::new()));
107        let l = log.clone();
108        let conditional = BoxConsumerOnce::new(move |x: &i32| {
109            l.lock().expect("mutex should not be poisoned").push(*x * 2);
110        })
111        .when(|x: &i32| *x > 0);
112        conditional.accept(&-5);
113        println!(
114            "  Conditional (negative): {:?}\n",
115            *log.lock().expect("mutex should not be poisoned")
116        );
117    }
118
119    // 4. Closure usage
120    println!("4. Closure usage");
121    {
122        let log = Arc::new(Mutex::new(Vec::new()));
123        let l = log.clone();
124        let closure = move |x: &i32| {
125            l.lock().expect("mutex should not be poisoned").push(*x * 2);
126            println!("  Closure consumed: {}", x);
127        };
128        closure.accept(&42);
129        println!(
130            "  Log: {:?}\n",
131            *log.lock().expect("mutex should not be poisoned")
132        );
133    }
134
135    // 5. Closure chaining
136    println!("5. Closure chaining");
137    {
138        let log = Arc::new(Mutex::new(Vec::new()));
139        let l1 = log.clone();
140        let l2 = log.clone();
141        let chained = (move |x: &i32| {
142            l1.lock()
143                .expect("mutex should not be poisoned")
144                .push(*x * 2);
145            println!("  Closure 1: {} * 2 = {}", x, x * 2);
146        })
147        .and_then(move |x: &i32| {
148            l2.lock()
149                .expect("mutex should not be poisoned")
150                .push(*x + 10);
151            println!("  Closure 2: {} + 10 = {}", x, x + 10);
152        });
153        chained.accept(&5);
154        println!(
155            "  Log: {:?}\n",
156            *log.lock().expect("mutex should not be poisoned")
157        );
158    }
159
160    // 6. Type conversions
161    println!("6. Type conversions");
162    {
163        let log = Arc::new(Mutex::new(Vec::new()));
164
165        // Closure to BoxConsumerOnce
166        let l = log.clone();
167        let closure = move |x: &i32| {
168            l.lock().expect("mutex should not be poisoned").push(*x);
169        };
170        let box_consumer = closure.into_box();
171        box_consumer.accept(&1);
172        println!(
173            "  BoxConsumerOnce: {:?}",
174            *log.lock().expect("mutex should not be poisoned")
175        );
176    }
177
178    // 7. Using with iterators (BoxConsumerOnce)
179    println!("7. Using with iterators");
180    {
181        let log = Arc::new(Mutex::new(Vec::new()));
182        let l = log.clone();
183        let consumer = BoxConsumerOnce::new(move |x: &i32| {
184            l.lock().expect("mutex should not be poisoned").push(*x * 2);
185        });
186        // Note: This will panic because BoxConsumerOnce can only be called once
187        // vec![1, 2, 3, 4, 5].iter().for_each(consumer.into_fn());
188        consumer.accept(&1);
189        println!(
190            "  BoxConsumerOnce with single value: {:?}\n",
191            *log.lock().expect("mutex should not be poisoned")
192        );
193    }
194
195    println!("=== Demo Complete ===");
196}
Source

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

Convert to closure

⚠️ Consumes self: The original consumer will be unavailable after calling this method.

Converts a one-time consumer to a closure that can be used directly in places where the standard library requires FnOnce.

§Default Implementation

The default implementation creates a closure that captures self and calls its accept method. Types can override this method to provide more efficient conversions.

§Returns

Returns a closure implementing FnOnce(&T)

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

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

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

Convert to BoxConsumerOnce without consuming self

⚠️ Requires Clone: This method requires Self to implement Clone. Clones the current consumer and wraps it in a BoxConsumerOnce.

§Default Implementation

The default implementation clones self and then calls into_box() on the clone. Types can override this method to provide more efficient conversions.

§Returns

Returns the wrapped BoxConsumerOnce<T>

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

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

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

Convert to closure without consuming self

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

§Default Implementation

The default implementation clones self and then calls into_fn() on the clone. Types can override this method to provide more efficient conversions.

§Returns

Returns a closure implementing FnOnce(&T)

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

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

Implementors§