qubit-function 0.8.1

Common functional programming type aliases for Rust, providing Java-style functional interfaces
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
/*******************************************************************************
 *
 *    Copyright (c) 2025 - 2026.
 *    Haixing Hu, Qubit Co. Ltd.
 *
 *    All rights reserved.
 *
 ******************************************************************************/
//! # MutatorOnce Tests
//!
//! Tests the complete functionality of MutatorOnce trait and its implementations.

use qubit_function::{
    BoxMutatorOnce,
    FnMutatorOnceOps,
    MutatorOnce,
};

// Test closures specialization and default behaviors
#[test]
fn test_closure_into_and_to_variants() {
    let data = vec![1, 2, 3];
    let closure = move |x: &mut Vec<i32>| x.extend(data);

    // into_box consumes the closure and returns BoxMutatorOnce
    let boxed = closure.into_box();
    let mut v = vec![0];
    boxed.apply(&mut v);
    assert_eq!(v, vec![0, 1, 2, 3]);

    // Note: closure was moved - create another closure for to_box/to_fn
    let closure2 = move |x: &mut Vec<i32>| x.push(99);
    // to_box uses Clone; simple closure is zero-sized and Clone, so to_box exists
    let boxed2 = closure2.to_box();
    let mut v2 = vec![0];
    boxed2.apply(&mut v2);
    assert_eq!(v2, vec![0, 99]);

    // to_fn for cloneable closure
    let closure3 = move |x: &mut Vec<i32>| x.push(7);
    let f = closure3.to_fn();
    let mut v3 = vec![0];
    f(&mut v3);
    assert_eq!(v3, vec![0, 7]);
}

#[test]
fn test_box_mutator_once_identity_and_chain() {
    // identity: into_box should be identity for BoxMutatorOnce
    let m = BoxMutatorOnce::new(|x: &mut Vec<i32>| x.push(1));
    let m2 = m.into_box();
    let mut v = Vec::new();
    m2.apply(&mut v);
    assert_eq!(v, vec![1]);

    // chain
    let m1 = BoxMutatorOnce::new(|x: &mut Vec<i32>| x.push(2));
    let m2 = BoxMutatorOnce::new(|x: &mut Vec<i32>| x.push(3));
    let chained = m1.and_then(m2);
    let mut v2 = Vec::new();
    chained.apply(&mut v2);
    assert_eq!(v2, vec![2, 3]);
}

// Custom MutatorOnce using default into_box/into_fn/to_box/to_fn
struct MyMutatorOnce {
    data: Vec<i32>,
}

impl MutatorOnce<Vec<i32>> for MyMutatorOnce {
    fn apply(self, value: &mut Vec<i32>) {
        value.extend(self.data);
    }
}

#[test]
fn test_custom_mutator_default_adapters() {
    let my = MyMutatorOnce { data: vec![4, 5] };
    let boxed = my.into_box();
    let mut v = vec![0];
    boxed.apply(&mut v);
    assert_eq!(v, vec![0, 4, 5]);

    // to test to_box/to_fn we need a cloneable type
    #[derive(Clone)]
    struct CloneMutator {
        data: Vec<i32>,
    }
    impl MutatorOnce<Vec<i32>> for CloneMutator {
        fn apply(self, value: &mut Vec<i32>) {
            value.extend(self.data);
        }
    }

    let c = CloneMutator { data: vec![6] };
    let boxed_c = c.to_box();
    let mut v2 = vec![0];
    boxed_c.apply(&mut v2);
    assert_eq!(v2, vec![0, 6]);

    let c2 = CloneMutator { data: vec![8] };
    let f = c2.to_fn();
    let mut v3 = vec![0];
    f(&mut v3);
    assert_eq!(v3, vec![0, 8]);
}

// ============================================================================
// Tests for MutatorOnce trait default implementations
// ============================================================================

#[test]
fn test_mutator_once_default_into_fn() {
    // Test the default implementation of into_fn() for custom MutatorOnce types
    let my = MyMutatorOnce { data: vec![10, 20] };
    let f = my.into_fn();
    let mut v = vec![0];
    f(&mut v);
    assert_eq!(v, vec![0, 10, 20]);
}

// ============================================================================
// Tests for BoxMutatorOnce
// ============================================================================

#[test]
fn test_box_mutator_once_noop() {
    // Test that noop() creates a mutator that does nothing
    let noop = BoxMutatorOnce::<i32>::noop();
    let mut value = 42;
    noop.apply(&mut value);
    assert_eq!(value, 42); // Value should remain unchanged

    // Test with Vec
    let noop_vec = BoxMutatorOnce::<Vec<i32>>::noop();
    let mut vec = vec![1, 2, 3];
    noop_vec.apply(&mut vec);
    assert_eq!(vec, vec![1, 2, 3]); // Vec should remain unchanged
}

#[test]
fn test_box_mutator_once_when() {
    // Test when() with condition that passes
    let data = vec![1, 2, 3];
    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data);
    });
    let conditional = mutator.when(|x: &Vec<i32>| !x.is_empty());

    let mut target = vec![0];
    conditional.apply(&mut target);
    assert_eq!(target, vec![0, 1, 2, 3]); // Should execute

    // Test when() with condition that fails
    let data2 = vec![4, 5];
    let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data2);
    });
    let conditional2 = mutator2.when(|x: &Vec<i32>| x.is_empty());

    let mut target2 = vec![0];
    conditional2.apply(&mut target2);
    assert_eq!(target2, vec![0]); // Should not execute
}

#[test]
fn test_box_mutator_once_into_fn() {
    // Test into_fn() for BoxMutatorOnce
    let mutator = BoxMutatorOnce::new(|x: &mut Vec<i32>| {
        x.push(100);
    });
    let f = mutator.into_fn();

    let mut v = vec![0];
    f(&mut v);
    assert_eq!(v, vec![0, 100]);
}

// ============================================================================
// Tests for BoxConditionalMutatorOnce
// ============================================================================

#[test]
fn test_box_conditional_mutator_once_mutate() {
    // Test mutate() when condition is true
    let data = vec![1, 2];
    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data);
    });
    let conditional = mutator.when(|x: &Vec<i32>| x.len() < 5);

    let mut target = vec![0];
    conditional.apply(&mut target);
    assert_eq!(target, vec![0, 1, 2]);

    // Test mutate() when condition is false
    let data2 = vec![3, 4];
    let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data2);
    });
    let conditional2 = mutator2.when(|x: &Vec<i32>| x.len() > 10);

    let mut target2 = vec![0];
    conditional2.apply(&mut target2);
    assert_eq!(target2, vec![0]); // Should remain unchanged
}

#[test]
fn test_box_conditional_mutator_once_into_box() {
    // Test into_box() conversion
    let data = vec![5, 6];
    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data);
    });
    let conditional = mutator.when(|x: &Vec<i32>| !x.is_empty());
    let boxed = conditional.into_box();

    let mut target = vec![0];
    boxed.apply(&mut target);
    assert_eq!(target, vec![0, 5, 6]);

    // Test with failing condition
    let data2 = vec![7, 8];
    let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data2);
    });
    let conditional2 = mutator2.when(|x: &Vec<i32>| x.is_empty());
    let boxed2 = conditional2.into_box();

    let mut target2 = vec![0];
    boxed2.apply(&mut target2);
    assert_eq!(target2, vec![0]); // Should remain unchanged
}

#[test]
fn test_box_conditional_mutator_once_into_fn() {
    // Test into_fn() conversion when condition is true
    let data = vec![9, 10];
    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data);
    });
    let conditional = mutator.when(|x: &Vec<i32>| x.len() < 10);
    let f = conditional.into_fn();

    let mut target = vec![0];
    f(&mut target);
    assert_eq!(target, vec![0, 9, 10]);

    // Test into_fn() conversion when condition is false
    let data2 = vec![11, 12];
    let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data2);
    });
    let conditional2 = mutator2.when(|x: &Vec<i32>| x.len() > 10);
    let f2 = conditional2.into_fn();

    let mut target2 = vec![0];
    f2(&mut target2);
    assert_eq!(target2, vec![0]); // Should remain unchanged due to condition being false
}

#[test]
fn test_box_conditional_mutator_once_and_then() {
    // Test and_then() to chain conditional mutators
    let data1 = vec![1, 2];
    let cond1 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data1);
    })
    .when(|x: &Vec<i32>| !x.is_empty());

    let data2 = vec![3, 4];
    let cond2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data2);
    })
    .when(|x: &Vec<i32>| x.len() < 10);

    let chained = cond1.and_then(cond2);

    let mut target = vec![0];
    chained.apply(&mut target);
    assert_eq!(target, vec![0, 1, 2, 3, 4]);

    // Test with one condition failing
    let data3 = vec![5, 6];
    let cond3 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data3);
    })
    .when(|x: &Vec<i32>| x.is_empty()); // This will fail

    let data4 = vec![7, 8];
    let cond4 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data4);
    })
    .when(|x: &Vec<i32>| x.len() < 10); // This will pass

    let chained2 = cond3.and_then(cond4);

    let mut target2 = vec![0];
    chained2.apply(&mut target2);
    assert_eq!(target2, vec![0, 7, 8]); // Only second mutator executes
}

#[test]
fn test_box_conditional_mutator_once_or_else() {
    // Test or_else() with condition true (when branch executes)
    let data1 = vec![1, 2, 3];
    let data2 = vec![99];
    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data1);
    })
    .when(|x: &Vec<i32>| !x.is_empty())
    .or_else(move |x: &mut Vec<i32>| {
        x.extend(data2);
    });

    let mut target = vec![0];
    mutator.apply(&mut target);
    assert_eq!(target, vec![0, 1, 2, 3]); // when branch executes

    // Test or_else() with condition false (or_else branch executes)
    let data3 = vec![4, 5];
    let data4 = vec![99];
    let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
        x.extend(data3);
    })
    .when(|x: &Vec<i32>| x.is_empty())
    .or_else(move |x: &mut Vec<i32>| {
        x.extend(data4);
    });

    let mut target2 = vec![0];
    mutator2.apply(&mut target2);
    assert_eq!(target2, vec![0, 99]); // or_else branch executes
}

// ============================================================================
// Tests for closure implementations
// ============================================================================

#[test]
fn test_closure_into_fn() {
    // Test into_fn() for closures
    let data = vec![1, 2, 3];
    let closure = move |x: &mut Vec<i32>| x.extend(data);
    let f = closure.into_fn();

    let mut v = vec![0];
    f(&mut v);
    assert_eq!(v, vec![0, 1, 2, 3]);
}

#[test]
fn test_closure_and_then() {
    // Test and_then() from FnMutatorOnceOps trait
    let data1 = vec![1, 2];
    let data2 = vec![3, 4];

    let chained =
        (move |x: &mut Vec<i32>| x.extend(data1)).and_then(move |x: &mut Vec<i32>| x.extend(data2));

    let mut target = vec![0];
    chained.apply(&mut target);
    assert_eq!(target, vec![0, 1, 2, 3, 4]);

    // Test chaining multiple closures
    let data3 = vec![5];
    let data4 = vec![6];
    let data5 = vec![7];

    let multi_chained = (move |x: &mut Vec<i32>| x.extend(data3))
        .and_then(move |x: &mut Vec<i32>| x.extend(data4))
        .and_then(move |x: &mut Vec<i32>| x.extend(data5));

    let mut target2 = vec![0];
    multi_chained.apply(&mut target2);
    assert_eq!(target2, vec![0, 5, 6, 7]);
}

// ============================================================================
// BoxConditionalMutatorOnce Debug/Display Tests
// ============================================================================

#[cfg(test)]
mod test_box_conditional_mutator_once_debug_display {
    use super::*;

    #[test]
    fn test_box_conditional_mutator_once_debug() {
        let data = vec![1, 2];
        let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| x.extend(data));
        let conditional = mutator.when(|x: &Vec<i32>| x.len() < 5);

        let debug_str = format!("{:?}", conditional);
        assert!(debug_str.contains("BoxConditionalMutatorOnce"));
        assert!(debug_str.contains("BoxMutatorOnce"));
        assert!(debug_str.contains("BoxPredicate"));
    }

    #[test]
    fn test_box_conditional_mutator_once_display() {
        let data = vec![3, 4];
        let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| x.extend(data));
        let conditional = mutator.when(|x: &Vec<i32>| !x.is_empty());

        let display_str = format!("{}", conditional);
        assert!(display_str.contains("BoxConditionalMutatorOnce"));
    }

    #[test]
    fn test_box_mutator_once_new_with_name() {
        let mutator = BoxMutatorOnce::new_with_name("test_mutator_once", |x: &mut i32| *x += 1);
        assert_eq!(mutator.name(), Some("test_mutator_once"));

        let mut value = 5;
        mutator.apply(&mut value);
        assert_eq!(value, 6);
    }

    #[test]
    fn test_box_mutator_once_new_with_optional_name_some() {
        let mutator = BoxMutatorOnce::new_with_optional_name(
            |x: &mut i32| *x += 1,
            Some("optional_once".to_string()),
        );
        assert_eq!(mutator.name(), Some("optional_once"));

        let mut value = 5;
        mutator.apply(&mut value);
        assert_eq!(value, 6);
    }

    #[test]
    fn test_box_mutator_once_new_with_optional_name_none() {
        let mutator = BoxMutatorOnce::new_with_optional_name(|x: &mut i32| *x += 1, None);
        assert_eq!(mutator.name(), None);

        let mut value = 5;
        mutator.apply(&mut value);
        assert_eq!(value, 6);
    }

    #[test]
    fn test_box_mutator_once_name_and_set_name() {
        let mut mutator = BoxMutatorOnce::new(|x: &mut i32| *x += 1);
        assert_eq!(mutator.name(), None);

        mutator.set_name("set_name_once");
        assert_eq!(mutator.name(), Some("set_name_once"));

        let mut value = 5;
        mutator.apply(&mut value);
        assert_eq!(value, 6);
    }
}

// Tests for to_box() method
#[cfg(test)]
mod custom_mutator_to_methods_tests {
    use super::*;
    use std::sync::{
        Arc,
        Mutex,
    };

    /// Cloneable custom mutator for testing to_xxx() methods
    #[derive(Clone)]
    struct CloneableMutator {
        log: Arc<Mutex<Vec<i32>>>,
        multiplier: i32,
    }

    impl CloneableMutator {
        fn new(log: Arc<Mutex<Vec<i32>>>, multiplier: i32) -> Self {
            Self { log, multiplier }
        }
    }

    impl MutatorOnce<i32> for CloneableMutator {
        fn apply(self, value: &mut i32) {
            *value *= self.multiplier;
            self.log.lock().unwrap().push(*value);
        }
    }

    #[test]
    fn test_custom_mutator_to_box() {
        let log = Arc::new(Mutex::new(Vec::new()));
        let mutator = CloneableMutator::new(log.clone(), 2);
        let boxed = mutator.to_box();
        let mut value = 7;
        boxed.apply(&mut value);
        assert_eq!(value, 14);
        assert_eq!(*log.lock().unwrap(), vec![14]);
    }

    #[test]
    fn test_custom_mutator_to_box_multiple_times() {
        let log = Arc::new(Mutex::new(Vec::new()));
        let mutator = CloneableMutator::new(log.clone(), 3);

        // to_box() should allow being called multiple times since the mutator is Clone
        let boxed1 = mutator.to_box();
        let boxed2 = mutator.to_box();

        let mut value1 = 6;
        boxed1.apply(&mut value1);
        assert_eq!(value1, 18);

        let mut value2 = 4;
        boxed2.apply(&mut value2);
        assert_eq!(value2, 12);

        assert_eq!(*log.lock().unwrap(), vec![18, 12]);
    }

    #[test]
    fn test_custom_mutator_to_box_original_still_usable() {
        let log = Arc::new(Mutex::new(Vec::new()));
        let mutator = CloneableMutator::new(log.clone(), 2);

        let boxed = mutator.to_box();
        let mut value1 = 5;
        boxed.apply(&mut value1);
        assert_eq!(value1, 10);

        // Original mutator should still be usable
        let mut value2 = 10;
        mutator.apply(&mut value2);
        assert_eq!(value2, 20);

        assert_eq!(*log.lock().unwrap(), vec![10, 20]);
    }
}