use qubit_function::{
BiMutatingFunctionOnce,
BoxBiMutatingFunctionOnce,
FnBiMutatingFunctionOnceOps,
};
fn append_strings_once(x: &mut String, y: &mut String) -> usize {
x.push_str("_modified");
y.push_str("_changed");
x.len() + y.len()
}
#[derive(Clone, Debug, PartialEq)]
struct TestStruct {
value: i32,
}
impl TestStruct {
fn new(value: i32) -> Self {
Self { value }
}
fn modify(&mut self, other: &mut Self) -> i32 {
self.value += other.value;
other.value *= 2;
self.value + other.value
}
}
fn modify_structs_once(a: &mut TestStruct, b: &mut TestStruct) -> i32 {
a.modify(b)
}
#[test]
fn test_bi_mutating_function_once_trait_apply() {
let swap_sum = |x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
};
let mut a = 20;
let mut b = 22;
assert_eq!(swap_sum.apply(&mut a, &mut b), 42);
assert_eq!(a, 22);
assert_eq!(b, 20);
}
#[test]
fn test_bi_mutating_function_once_trait_apply_with_complex_types() {
let modify = |a: &mut TestStruct, b: &mut TestStruct| a.modify(b);
let mut s1 = TestStruct::new(10);
let mut s2 = TestStruct::new(5);
let result = modify.apply(&mut s1, &mut s2);
assert_eq!(result, 25); assert_eq!(s1.value, 15);
assert_eq!(s2.value, 10);
}
#[test]
fn test_bi_mutating_function_once_trait_into_box() {
let swap_sum = |x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
};
let boxed = BiMutatingFunctionOnce::into_box(swap_sum);
let mut a = 20;
let mut b = 22;
assert_eq!(boxed.apply(&mut a, &mut b), 42);
assert_eq!(a, 22);
assert_eq!(b, 20);
}
#[test]
fn test_bi_mutating_function_once_trait_into_fn() {
let swap_sum = |x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
};
let func = BiMutatingFunctionOnce::into_fn(swap_sum);
let mut a = 20;
let mut b = 22;
assert_eq!(func(&mut a, &mut b), 42);
assert_eq!(a, 22);
assert_eq!(b, 20);
}
#[test]
fn test_bi_mutating_function_once_trait_to_box() {
let swap_sum = |x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
};
let boxed = swap_sum.to_box();
let mut a = 20;
let mut b = 22;
assert_eq!(boxed.apply(&mut a, &mut b), 42);
assert_eq!(a, 22);
assert_eq!(b, 20);
let mut c = 30;
let mut d = 32;
assert_eq!(swap_sum.apply(&mut c, &mut d), 62);
}
#[test]
fn test_bi_mutating_function_once_trait_to_fn() {
let swap_sum = |x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
};
let func = swap_sum.to_fn();
let mut a = 20;
let mut b = 22;
assert_eq!(func(&mut a, &mut b), 42);
assert_eq!(a, 22);
assert_eq!(b, 20);
let mut c = 30;
let mut d = 32;
assert_eq!(swap_sum.apply(&mut c, &mut d), 62);
}
#[test]
fn test_box_bi_mutating_function_once_new() {
let swap_sum = BoxBiMutatingFunctionOnce::new(|x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
});
let mut a = 10;
let mut b = 15;
assert_eq!(swap_sum.apply(&mut a, &mut b), 25);
assert_eq!(a, 15);
assert_eq!(b, 10);
}
#[test]
fn test_box_bi_mutating_function_once_new_allows_non_static_t() {
fn run<'a>(value: &'a str) -> usize {
let func: BoxBiMutatingFunctionOnce<&'a str, i32, usize> =
BoxBiMutatingFunctionOnce::new(|x: &mut &'a str, y: &mut i32| x.len() + (*y as usize));
let mut first = value;
let mut second = 3;
func.apply(&mut first, &mut second)
}
let text = String::from("hello");
assert_eq!(run(text.as_str()), 8);
}
#[test]
fn test_box_bi_mutating_function_once_new_allows_non_static_u() {
fn run<'a>(value: &'a str) -> usize {
let func: BoxBiMutatingFunctionOnce<i32, &'a str, usize> =
BoxBiMutatingFunctionOnce::new(|x: &mut i32, y: &mut &'a str| (*x as usize) + y.len());
let mut first = 3;
let mut second = value;
func.apply(&mut first, &mut second)
}
let text = String::from("world");
assert_eq!(run(text.as_str()), 8);
}
#[test]
fn test_box_bi_mutating_function_once_new_allows_non_static_r() {
fn run<'a>(value: &'a str) -> &'a str {
let func: BoxBiMutatingFunctionOnce<&'a str, i32, &'a str> =
BoxBiMutatingFunctionOnce::new(|x: &mut &'a str, _y: &mut i32| *x);
let mut first = value;
let mut second = 0;
func.apply(&mut first, &mut second)
}
let text = String::from("qubit");
assert_eq!(run(text.as_str()), "qubit");
}
#[test]
fn test_box_bi_mutating_function_once_new_with_name() {
let swap_sum = BoxBiMutatingFunctionOnce::new_with_name(
"swap_and_sum_once",
|x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
},
);
assert_eq!(swap_sum.name(), Some("swap_and_sum_once"));
let mut a = 10;
let mut b = 15;
assert_eq!(swap_sum.apply(&mut a, &mut b), 25);
}
#[test]
fn test_box_bi_mutating_function_once_new_with_optional_name() {
let swap_sum = BoxBiMutatingFunctionOnce::new_with_optional_name(
|x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
},
Some("test_function_once".to_string()),
);
assert_eq!(swap_sum.name(), Some("test_function_once"));
let no_name =
BoxBiMutatingFunctionOnce::new_with_optional_name(|x: &mut i32, y: &mut i32| *x + *y, None);
assert_eq!(no_name.name(), None);
}
#[test]
fn test_box_bi_mutating_function_once_name_and_set_name() {
let mut swap_sum = BoxBiMutatingFunctionOnce::new(|x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
});
assert_eq!(swap_sum.name(), None);
swap_sum.set_name("modified_name_once");
assert_eq!(swap_sum.name(), Some("modified_name_once"));
swap_sum.set_name("another_name_once");
assert_eq!(swap_sum.name(), Some("another_name_once"));
}
#[test]
fn test_box_bi_mutating_function_once_constant() {
let constant = BoxBiMutatingFunctionOnce::constant(42);
let mut a = 1;
let mut b = 2;
assert_eq!(constant.apply(&mut a, &mut b), 42);
assert_eq!(a, 1); assert_eq!(b, 2);
}
#[test]
fn test_box_bi_mutating_function_once_debug_display() {
let swap_sum = BoxBiMutatingFunctionOnce::new(|x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
});
let debug_str = format!("{:?}", swap_sum);
assert!(debug_str.contains("BoxBiMutatingFunctionOnce"));
let display_str = format!("{}", swap_sum);
assert!(display_str.contains("BoxBiMutatingFunctionOnce"));
}
#[test]
fn test_box_bi_mutating_function_once_with_strings() {
let append = BoxBiMutatingFunctionOnce::new(append_strings_once);
let mut s1 = "hello".to_string();
let mut s2 = "world".to_string();
let result = append.apply(&mut s1, &mut s2);
assert_eq!(result, 14 + 13); assert_eq!(s1, "hello_modified");
assert_eq!(s2, "world_changed");
}
#[test]
fn test_box_bi_mutating_function_once_with_structs() {
let modify = BoxBiMutatingFunctionOnce::new(modify_structs_once);
let mut s1 = TestStruct::new(10);
let mut s2 = TestStruct::new(5);
let result = modify.apply(&mut s1, &mut s2);
assert_eq!(result, 25); assert_eq!(s1.value, 15);
assert_eq!(s2.value, 10);
}
#[test]
fn test_box_bi_mutating_function_once_one_time_use() {
let counter = std::rc::Rc::new(std::cell::RefCell::new(0));
let counter_clone = std::rc::Rc::clone(&counter);
let increment = BoxBiMutatingFunctionOnce::new(move |x: &mut i32, y: &mut i32| {
*counter_clone.borrow_mut() += 1;
*x += 1;
*y += 1;
*x + *y
});
let mut a = 10;
let mut b = 20;
assert_eq!(increment.apply(&mut a, &mut b), 32); assert_eq!(*counter.borrow(), 1);
assert_eq!(a, 11);
assert_eq!(b, 21);
}
#[test]
fn test_fn_bi_mutating_function_once_ops_and_then() {
let swap_and_sum = |x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
};
let double = |result: &i32| *result * 2;
let composed = swap_and_sum.and_then(double);
let mut a = 3;
let mut b = 5;
assert_eq!(composed.apply(&mut a, &mut b), 16);
assert_eq!(a, 5);
assert_eq!(b, 3);
}
#[test]
fn test_fn_bi_mutating_function_once_ops_and_then_chain() {
let add_and_modify = |x: &mut i32, y: &mut i32| {
*x += 10;
*y += 20;
*x + *y
};
let to_string = |x: &i32| x.to_string();
let add_prefix = |s: &mut String| {
let result = format!("Result: {}", *s);
*s = String::new();
result
};
let composed = add_and_modify.and_then(to_string).and_then(add_prefix);
let mut a = 5;
let mut b = 3;
let result = composed.apply(&mut a, &mut b);
assert_eq!(result, "Result: 38");
assert_eq!(a, 15);
assert_eq!(b, 23);
}
#[test]
fn test_fn_bi_mutating_function_once_ops_when_or_else() {
let swap_and_sum = |x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
};
let multiply = |x: &mut i32, y: &mut i32| {
*x *= *y;
*x
};
let conditional = swap_and_sum
.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
.or_else(multiply);
let mut a = 5;
let mut b = 3;
assert_eq!(conditional.apply(&mut a, &mut b), 8); assert_eq!(a, 3); assert_eq!(b, 5);
let conditional_false = swap_and_sum
.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
.or_else(multiply);
let mut c = -5;
let mut d = 3;
assert_eq!(conditional_false.apply(&mut c, &mut d), -15); assert_eq!(c, -15);
assert_eq!(d, 3);
}
#[test]
fn test_box_conditional_bi_mutating_function_once() {
let swap_and_sum = BoxBiMutatingFunctionOnce::new(|x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
});
let multiply = BoxBiMutatingFunctionOnce::new(|x: &mut i32, y: &mut i32| {
*x *= *y;
*x
});
let conditional = swap_and_sum
.when(|x: &i32, _y: &i32| *x > 0)
.or_else(multiply);
let mut a = 5;
let mut b = 3;
assert_eq!(conditional.apply(&mut a, &mut b), 8);
let conditional2 = BoxBiMutatingFunctionOnce::new(|x: &mut i32, y: &mut i32| {
std::mem::swap(&mut *x, &mut *y);
*x + *y
})
.when(|x: &i32, _y: &i32| *x > 0)
.or_else(BoxBiMutatingFunctionOnce::new(
|x: &mut i32, y: &mut i32| {
*x *= *y;
*x
},
));
let mut c = -5;
let mut d = 3;
assert_eq!(conditional2.apply(&mut c, &mut d), -15); }
#[test]
fn test_conditional_bi_mutating_function_once_with_structs() {
let modify = BoxBiMutatingFunctionOnce::new(modify_structs_once);
let no_op = BoxBiMutatingFunctionOnce::new(|_a: &mut TestStruct, _b: &mut TestStruct| 0);
let conditional = modify
.when(|a: &TestStruct, b: &TestStruct| a.value > 0 && b.value > 0)
.or_else(no_op);
let mut s1 = TestStruct::new(10);
let mut s2 = TestStruct::new(5);
let result = conditional.apply(&mut s1, &mut s2);
assert_eq!(result, 25); assert_eq!(s1.value, 15);
assert_eq!(s2.value, 10);
let conditional2 = BoxBiMutatingFunctionOnce::new(modify_structs_once)
.when(|a: &TestStruct, b: &TestStruct| a.value > 0 && b.value > 0)
.or_else(BoxBiMutatingFunctionOnce::new(
|_a: &mut TestStruct, _b: &mut TestStruct| 0,
));
let mut s3 = TestStruct::new(-10);
let mut s4 = TestStruct::new(5);
let result2 = conditional2.apply(&mut s3, &mut s4);
assert_eq!(result2, 0); assert_eq!(s3.value, -10); assert_eq!(s4.value, 5); }
#[test]
fn test_bi_mutating_function_once_with_zero_values() {
let add = |x: &mut i32, y: &mut i32| {
*x += *y;
*x
};
let mut a = 0;
let mut b = 0;
assert_eq!(add.apply(&mut a, &mut b), 0);
assert_eq!(a, 0);
assert_eq!(b, 0);
let mut c = 0;
let mut d = 5;
assert_eq!(add.apply(&mut c, &mut d), 5);
assert_eq!(c, 5);
assert_eq!(d, 5);
}
#[test]
fn test_bi_mutating_function_once_with_negative_values() {
let multiply = |x: &mut i32, y: &mut i32| {
*x *= *y;
*x
};
let mut a = -5;
let mut b = 3;
assert_eq!(multiply.apply(&mut a, &mut b), -15);
assert_eq!(a, -15);
assert_eq!(b, 3);
let mut c = -2;
let mut d = -4;
assert_eq!(multiply.apply(&mut c, &mut d), 8);
assert_eq!(c, 8);
assert_eq!(d, -4);
}
#[test]
fn test_bi_mutating_function_once_with_large_values() {
let add = |x: &mut i64, y: &mut i64| {
*x += *y;
*x
};
let mut a = i64::MAX - 10;
let mut b = 5;
assert_eq!(add.apply(&mut a, &mut b), i64::MAX - 5);
assert_eq!(a, i64::MAX - 5);
assert_eq!(b, 5);
}
#[test]
fn test_bi_mutating_function_once_with_empty_strings() {
let concat = |x: &mut String, y: &mut String| {
x.push_str(y);
x.len()
};
let mut s1 = String::new();
let mut s2 = String::new();
assert_eq!(concat.apply(&mut s1, &mut s2), 0);
assert_eq!(s1, "");
assert_eq!(s2, "");
let mut s3 = "hello".to_string();
let mut s4 = String::new();
assert_eq!(concat.apply(&mut s3, &mut s4), 5);
assert_eq!(s3, "hello");
assert_eq!(s4, "");
}
#[test]
fn test_bi_mutating_function_once_with_unicode_strings() {
let append = |x: &mut String, y: &mut String| {
x.push('🌟');
y.push('⭐');
x.len() + y.len()
};
let mut s1 = "Hello".to_string();
let mut s2 = "World".to_string();
let result = append.apply(&mut s1, &mut s2);
assert_eq!(s1, "Hello🌟");
assert_eq!(s2, "World⭐");
assert_eq!(result, 9 + 8); }
#[test]
fn test_bi_mutating_function_once_identity_operations() {
let sum = |x: &mut i32, y: &mut i32| *x + *y;
let mut a = 10;
let mut b = 20;
assert_eq!(sum.apply(&mut a, &mut b), 30);
assert_eq!(a, 10); assert_eq!(b, 20); }
#[test]
fn test_bi_mutating_function_once_chained_modifications() {
let complex_op = |x: &mut i32, y: &mut i32| {
*x = *x * 2 + *y;
*y = *y * 3 - *x;
*x + *y
};
let mut a = 3;
let mut b = 5;
let result = complex_op.apply(&mut a, &mut b);
assert_eq!(result, 15);
assert_eq!(a, 11);
assert_eq!(b, 4);
}
#[test]
#[should_panic]
fn test_bi_mutating_function_once_panic_in_closure() {
let panic_func = |x: &mut i32, y: &mut i32| {
if *x < 0 {
panic!("Negative value not allowed");
}
*x + *y
};
let mut a = -5;
let mut b = 10;
let _ = panic_func.apply(&mut a, &mut b);
}
#[test]
fn test_bi_mutating_function_once_with_option_modification() {
let modify_option = |x: &mut Option<i32>, y: &mut Option<i32>| {
if let (Some(val1), Some(val2)) = (*x, *y) {
*x = Some(val1 + val2);
*y = Some(val1 * val2);
val1 + val2
} else {
0
}
};
let mut a = Some(10);
let mut b = Some(5);
let result = modify_option.apply(&mut a, &mut b);
assert_eq!(result, 15);
assert_eq!(a, Some(15));
assert_eq!(b, Some(50));
let mut c = None;
let mut d = Some(5);
let result2 = modify_option.apply(&mut c, &mut d);
assert_eq!(result2, 0);
assert_eq!(c, None);
assert_eq!(d, Some(5));
}
#[test]
fn test_box_bi_mutating_function_once_consumption() {
let create_func = || {
BoxBiMutatingFunctionOnce::new(|x: &mut i32, y: &mut i32| {
*x += 1;
*y += 1;
*x + *y
})
};
let func = create_func();
let mut a = 10;
let mut b = 20;
let result = func.apply(&mut a, &mut b);
assert_eq!(result, 32); assert_eq!(a, 11);
assert_eq!(b, 21);
let func2 = create_func();
let mut c = 30;
let mut d = 40;
let result2 = func2.apply(&mut c, &mut d);
assert_eq!(result2, 72); assert_eq!(c, 31);
assert_eq!(d, 41);
}
#[test]
fn test_bi_mutating_function_once_with_moving_data() {
let data = vec![1, 2, 3];
let func = |x: &mut Vec<i32>, y: &mut Vec<i32>| {
x.extend_from_slice(&data);
y.push(42);
x.len() + y.len()
};
let mut v1 = vec![10];
let mut v2 = vec![20];
let result = func.apply(&mut v1, &mut v2);
assert_eq!(result, 6); assert_eq!(v1, vec![10, 1, 2, 3]);
assert_eq!(v2, vec![20, 42]);
}
#[test]
fn test_complex_conditional_chains() {
let add = |x: &mut i32, y: &mut i32| {
*x += *y;
*x
};
let subtract = |x: &mut i32, y: &mut i32| {
*x -= *y;
*x
};
let multiply = |x: &mut i32, y: &mut i32| {
*x *= *y;
*x
};
let complex = add
.when(|x: &i32, y: &i32| *x > *y)
.or_else(multiply.when(|x: &i32, _y: &i32| *x < 0).or_else(subtract));
let mut a = 10;
let mut b = 5;
assert_eq!(complex.apply(&mut a, &mut b), 15);
let complex2 = add
.when(|x: &i32, y: &i32| *x > *y)
.or_else(multiply.when(|x: &i32, _y: &i32| *x < 0).or_else(subtract));
let mut c = -3;
let mut d = 4;
assert_eq!(complex2.apply(&mut c, &mut d), -12);
let complex3 = add
.when(|x: &i32, y: &i32| *x > *y)
.or_else(multiply.when(|x: &i32, _y: &i32| *x < 0).or_else(subtract));
let mut e = 3;
let mut f = 5;
assert_eq!(complex3.apply(&mut e, &mut f), -2); }
#[test]
fn test_nested_composition() {
let base = |x: &mut i32, y: &mut i32| {
*x += 1;
*y += 1;
*x + *y
};
let inner_composed = base.and_then(|sum: &i32| *sum * 2);
let outer_composed = inner_composed.and_then(|doubled: &mut i32| {
let result = format!("Result: {}", *doubled);
*doubled = 0;
result
});
let mut a = 10;
let mut b = 20;
let result = outer_composed.apply(&mut a, &mut b);
assert_eq!(result, "Result: 64");
assert_eq!(a, 11);
assert_eq!(b, 21);
}
#[test]
fn test_mixed_function_types() {
let mutating = |x: &mut i32, y: &mut i32| {
*x += 10;
*y += 20;
*x + *y
};
let double = |x: &i32| *x * 2;
let composed = mutating.and_then(double);
let mut a = 5;
let mut b = 3;
assert_eq!(composed.apply(&mut a, &mut b), 76);
assert_eq!(a, 15);
assert_eq!(b, 23);
}
#[test]
fn test_custom_bi_mutating_function_once_default_methods() {
#[derive(Debug)]
struct CustomBiMutatingFunctionOnce {
multiplier: i32,
}
impl BiMutatingFunctionOnce<i32, i32, i32> for CustomBiMutatingFunctionOnce {
fn apply(self, first: &mut i32, second: &mut i32) -> i32 {
*first *= self.multiplier;
*second += self.multiplier;
*first + *second
}
}
let custom_func = CustomBiMutatingFunctionOnce { multiplier: 3 };
let mut a = 2;
let mut b = 4;
let boxed = custom_func.into_box();
let result = boxed.apply(&mut a, &mut b);
assert_eq!(result, 13); assert_eq!(a, 6);
assert_eq!(b, 7);
}
#[test]
fn test_cloneable_bi_mutating_function_once_default_methods() {
#[derive(Clone, Debug)]
struct CloneableBiMutatingFunctionOnce {
multiplier: i32,
}
impl BiMutatingFunctionOnce<i32, i32, i32> for CloneableBiMutatingFunctionOnce {
fn apply(self, first: &mut i32, second: &mut i32) -> i32 {
*first *= self.multiplier;
*second += self.multiplier;
*first + *second
}
}
let custom_func = CloneableBiMutatingFunctionOnce { multiplier: 2 };
let mut a = 3;
let mut b = 5;
let boxed = custom_func.to_box();
let result = boxed.apply(&mut a, &mut b);
assert_eq!(result, 13); assert_eq!(a, 6);
assert_eq!(b, 7);
let func = custom_func.to_fn();
let mut c = 1;
let mut d = 2;
let result2 = func(&mut c, &mut d);
assert_eq!(result2, 6); assert_eq!(c, 2);
assert_eq!(d, 4);
}