Skip to main content

mutator_once_conditional_demo/
mutator_once_conditional_demo.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # MutatorOnce Conditional Execution Demo
10//!
11//! Demonstrates conditional execution features of BoxMutatorOnce
12
13use qubit_function::{
14    BoxMutatorOnce,
15    BoxPredicate,
16    FnPredicateOps,
17    MutatorOnce,
18};
19
20fn main() {
21    println!("=== MutatorOnce Conditional Execution Examples ===\n");
22
23    // 1. Basic conditional execution - when condition is satisfied
24    println!("1. Basic conditional execution - when condition is satisfied");
25    let data = vec![1, 2, 3];
26    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
27        println!("   Extending vector with data: {:?}", data);
28        x.extend(data);
29    });
30    let conditional = mutator.when(|x: &Vec<i32>| {
31        println!("   Checking condition: !x.is_empty()");
32        !x.is_empty()
33    });
34
35    let mut target = vec![0];
36    println!("   Initial: {:?}", target);
37    conditional.apply(&mut target);
38    println!("   Result: {:?}\n", target);
39
40    // 2. Conditional execution - when condition is not satisfied
41    println!("2. Conditional execution - when condition is not satisfied");
42    let data = vec![4, 5, 6];
43    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
44        println!("   This should not be executed");
45        x.extend(data);
46    });
47    let conditional = mutator.when(|x: &Vec<i32>| {
48        println!("   Checking condition: x.len() > 10");
49        x.len() > 10
50    });
51
52    let mut target = vec![0];
53    println!("   Initial: {:?}", target);
54    conditional.apply(&mut target);
55    println!("   Result: {:?} (unchanged)\n", target);
56
57    // 3. Using BoxPredicate
58    println!("3. Using BoxPredicate");
59    let pred = BoxPredicate::new(|x: &Vec<i32>| {
60        println!("   Predicate: checking if vector is not empty");
61        !x.is_empty()
62    });
63    let data = vec![7, 8, 9];
64    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
65        println!("   Adding data: {:?}", data);
66        x.extend(data);
67    });
68    let conditional = mutator.when(pred);
69
70    let mut target = vec![0];
71    println!("   Initial: {:?}", target);
72    conditional.apply(&mut target);
73    println!("   Result: {:?}\n", target);
74
75    // 4. Using composed predicate
76    println!("4. Using composed predicate");
77    let pred = (|x: &Vec<i32>| {
78        println!("   Condition 1: !x.is_empty()");
79        !x.is_empty()
80    })
81    .and(|x: &Vec<i32>| {
82        println!("   Condition 2: x.len() < 10");
83        x.len() < 10
84    });
85    let data = vec![10, 11, 12];
86    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
87        println!("   Adding data: {:?}", data);
88        x.extend(data);
89    });
90    let conditional = mutator.when(pred);
91
92    let mut target = vec![0];
93    println!("   Initial: {:?}", target);
94    conditional.apply(&mut target);
95    println!("   Result: {:?}\n", target);
96
97    // 5. If-then-else with or_else - when branch
98    println!("5. If-then-else with or_else - when branch");
99    let data1 = vec![1, 2, 3];
100    let data2 = vec![99];
101    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
102        println!("   When branch: adding {:?}", data1);
103        x.extend(data1);
104    })
105    .when(|x: &Vec<i32>| {
106        println!("   Checking: !x.is_empty()");
107        !x.is_empty()
108    })
109    .or_else(move |x: &mut Vec<i32>| {
110        println!("   Else branch: adding {:?}", data2);
111        x.extend(data2);
112    });
113
114    let mut target = vec![0];
115    println!("   Initial: {:?}", target);
116    mutator.apply(&mut target);
117    println!("   Result: {:?}\n", target);
118
119    // 6. If-then-else with or_else - else branch
120    println!("6. If-then-else with or_else - else branch");
121    let data1 = vec![4, 5, 6];
122    let data2 = vec![99];
123    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
124        println!("   When branch: adding {:?}", data1);
125        x.extend(data1);
126    })
127    .when(|x: &Vec<i32>| {
128        println!("   Checking: x.is_empty()");
129        x.is_empty()
130    })
131    .or_else(move |x: &mut Vec<i32>| {
132        println!("   Else branch: adding {:?}", data2);
133        x.extend(data2);
134    });
135
136    let mut target = vec![0];
137    println!("   Initial: {:?}", target);
138    mutator.apply(&mut target);
139    println!("   Result: {:?}\n", target);
140
141    // 7. Conditional with integers
142    println!("7. Conditional with integers");
143    let mutator = BoxMutatorOnce::new(|x: &mut i32| {
144        println!("   Multiplying by 2");
145        *x *= 2;
146    })
147    .when(|x: &i32| {
148        println!("   Checking: *x > 0");
149        *x > 0
150    });
151
152    let mut positive = 5;
153    println!("   Initial (positive): {}", positive);
154    mutator.apply(&mut positive);
155    println!("   Result: {}\n", positive);
156
157    // 8. Conditional with integers - not executed
158    println!("8. Conditional with integers - not executed");
159    let mutator = BoxMutatorOnce::new(|x: &mut i32| {
160        println!("   This should not be executed");
161        *x *= 2;
162    })
163    .when(|x: &i32| {
164        println!("   Checking: *x > 0");
165        *x > 0
166    });
167
168    let mut negative = -5;
169    println!("   Initial (negative): {}", negative);
170    mutator.apply(&mut negative);
171    println!("   Result: {} (unchanged)\n", negative);
172
173    // 9. Chaining conditional mutators
174    println!("9. Chaining conditional mutators");
175    let data1 = vec![1, 2];
176    let cond1 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
177        println!("   First mutator: adding {:?}", data1);
178        x.extend(data1);
179    })
180    .when(|x: &Vec<i32>| {
181        println!("   First condition: !x.is_empty()");
182        !x.is_empty()
183    });
184
185    let data2 = vec![3, 4];
186    let cond2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
187        println!("   Second mutator: adding {:?}", data2);
188        x.extend(data2);
189    })
190    .when(|x: &Vec<i32>| {
191        println!("   Second condition: x.len() < 10");
192        x.len() < 10
193    });
194
195    let chained = cond1.and_then(cond2);
196
197    let mut target = vec![0];
198    println!("   Initial: {:?}", target);
199    chained.apply(&mut target);
200    println!("   Result: {:?}\n", target);
201
202    // 10. Complex conditional chain
203    println!("10. Complex conditional chain");
204    let data1 = vec![1, 2];
205    let data2 = vec![99];
206    let data3 = vec![5, 6];
207
208    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
209        println!("   When branch: adding {:?}", data1);
210        x.extend(data1);
211    })
212    .when(|x: &Vec<i32>| {
213        println!("   Checking: !x.is_empty()");
214        !x.is_empty()
215    })
216    .or_else(move |x: &mut Vec<i32>| {
217        println!("   Else branch: adding {:?}", data2);
218        x.extend(data2);
219    })
220    .and_then(move |x: &mut Vec<i32>| {
221        println!("   Final step: adding {:?}", data3);
222        x.extend(data3);
223    });
224
225    let mut target = vec![0];
226    println!("   Initial: {:?}", target);
227    mutator.apply(&mut target);
228    println!("   Result: {:?}\n", target);
229
230    // 11. Real-world scenario: data validation and processing
231    println!("11. Real-world scenario: data validation and processing");
232
233    struct DataProcessor {
234        on_valid: Option<BoxMutatorOnce<Vec<String>>>,
235        on_invalid: Option<BoxMutatorOnce<Vec<String>>>,
236    }
237
238    impl DataProcessor {
239        fn new<V, I>(on_valid: V, on_invalid: I) -> Self
240        where
241            V: FnOnce(&mut Vec<String>) + 'static,
242            I: FnOnce(&mut Vec<String>) + 'static,
243        {
244            Self {
245                on_valid: Some(BoxMutatorOnce::new(on_valid)),
246                on_invalid: Some(BoxMutatorOnce::new(on_invalid)),
247            }
248        }
249
250        fn process(mut self, data: &mut Vec<String>) {
251            let is_valid = !data.is_empty() && data.iter().all(|s| !s.is_empty());
252            println!(
253                "   Data validation: {}",
254                if is_valid { "VALID" } else { "INVALID" }
255            );
256
257            if is_valid {
258                if let Some(callback) = self.on_valid.take() {
259                    callback.apply(data);
260                }
261            } else if let Some(callback) = self.on_invalid.take() {
262                callback.apply(data);
263            }
264        }
265    }
266
267    let valid_suffix = vec!["processed".to_string()];
268    let invalid_marker = vec!["[INVALID]".to_string()];
269
270    let processor = DataProcessor::new(
271        move |data| {
272            println!("   Valid data callback: adding suffix");
273            data.extend(valid_suffix);
274        },
275        move |data| {
276            println!("   Invalid data callback: adding error marker");
277            data.clear();
278            data.extend(invalid_marker);
279        },
280    );
281
282    let mut valid_data = vec!["item1".to_string(), "item2".to_string()];
283    println!("   Processing valid data: {:?}", valid_data);
284    processor.process(&mut valid_data);
285    println!("   Result: {:?}\n", valid_data);
286
287    println!("=== Examples completed ===");
288}