use qubit_function::{
BoxMutatingFunctionOnce,
FnMutatingFunctionOnceOps,
MutatingFunctionOnce,
};
#[derive(Clone)]
struct TestMutatingFunctionOnce {
multiplier: i32,
}
impl TestMutatingFunctionOnce {
fn new(multiplier: i32) -> Self {
TestMutatingFunctionOnce { multiplier }
}
}
impl MutatingFunctionOnce<i32, i32> for TestMutatingFunctionOnce {
fn apply(self, input: &mut i32) -> i32 {
let old_value = *input;
*input *= self.multiplier;
old_value
}
}
#[cfg(test)]
mod test_mutating_function_once_default_impl {
use super::*;
#[test]
fn test_into_box() {
let func = TestMutatingFunctionOnce::new(2);
let boxed = func.into_box();
let mut value = 5;
assert_eq!(boxed.apply(&mut value), 5);
assert_eq!(value, 10);
}
#[test]
fn test_into_fn() {
let func = TestMutatingFunctionOnce::new(3);
let closure = func.into_fn();
let mut value = 4;
assert_eq!(closure(&mut value), 4);
assert_eq!(value, 12);
}
#[test]
fn test_to_box() {
let func = TestMutatingFunctionOnce::new(2);
let boxed = func.to_box();
let mut value = 5;
assert_eq!(boxed.apply(&mut value), 5);
assert_eq!(value, 10);
}
#[test]
fn test_to_fn() {
let func = TestMutatingFunctionOnce::new(3);
let closure = func.to_fn();
let mut value = 4;
assert_eq!(closure(&mut value), 4);
assert_eq!(value, 12);
}
}
#[cfg(test)]
mod test_box_mutating_function_once {
use super::*;
#[test]
fn test_new() {
let data = vec![1, 2, 3];
let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
});
let mut target = vec![0];
let old_len = func.apply(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_new_allows_non_static_t() {
fn run<'a>(value: &'a str) -> usize {
let func: BoxMutatingFunctionOnce<&'a str, usize> =
BoxMutatingFunctionOnce::new(|x: &mut &'a str| x.len());
let mut input = value;
func.apply(&mut input)
}
let text = String::from("hello");
assert_eq!(run(text.as_str()), 5);
}
#[test]
fn test_new_allows_non_static_r() {
fn run<'a>(value: &'a str) -> &'a str {
let func: BoxMutatingFunctionOnce<&'a str, &'a str> =
BoxMutatingFunctionOnce::new(|x: &mut &'a str| *x);
let mut input = value;
func.apply(&mut input)
}
let text = String::from("qubit");
assert_eq!(run(text.as_str()), "qubit");
}
#[test]
fn test_with_string() {
let data = String::from(" world");
let func = BoxMutatingFunctionOnce::new(move |x: &mut String| {
let old_len = x.len();
x.push_str(&data);
old_len
});
let mut target = String::from("hello");
let old_len = func.apply(&mut target);
assert_eq!(old_len, 5);
assert_eq!(target, "hello world");
}
#[test]
fn test_and_then() {
let data1 = vec![1, 2];
let data2 = [3, 4];
let chained = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
x.extend(data1);
x.len()
})
.and_then(move |len: &usize| {
*len + data2.len()
});
let mut target = vec![0];
let final_len = chained.apply(&mut target);
assert_eq!(final_len, 5); assert_eq!(target, vec![0, 1, 2]);
}
#[test]
fn test_and_then_multiple_chains() {
let data1 = vec![1, 2];
let data2 = [3, 4];
let data3 = [5, 6];
let chained = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
x.extend(data1);
x.len()
})
.and_then(move |len: &usize| {
*len + data2.len()
})
.and_then(move |len: &usize| {
*len + data3.len()
});
let mut target = vec![0];
let final_len = chained.apply(&mut target);
assert_eq!(final_len, 7); assert_eq!(target, vec![0, 1, 2]);
}
#[test]
fn test_identity() {
let identity = BoxMutatingFunctionOnce::<i32, i32>::identity();
let mut value = 42;
let result = identity.apply(&mut value);
assert_eq!(result, 42);
assert_eq!(value, 42);
}
#[test]
fn test_map() {
let data = vec![1, 2, 3];
let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
});
let mapped =
func.and_then::<String, _>(|old_len: &usize| format!("Old length: {}", *old_len));
let mut target = vec![0];
let result = mapped.apply(&mut target);
assert_eq!(result, "Old length: 1");
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_validation_pattern() {
struct Data {
value: i32,
}
let validator = BoxMutatingFunctionOnce::new(|data: &mut Data| {
if data.value < 0 {
data.value = 0;
Err("Fixed negative value")
} else {
Ok("Valid")
}
});
let mut data = Data { value: -5 };
let result = validator.apply(&mut data);
assert_eq!(data.value, 0);
assert!(result.is_err());
}
#[test]
fn test_resource_transfer() {
let resource = vec![1, 2, 3, 4, 5];
let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
let old_sum: i32 = x.iter().sum();
x.extend(resource);
old_sum
});
let mut target = vec![10, 20];
let old_sum = func.apply(&mut target);
assert_eq!(old_sum, 30);
assert_eq!(target, vec![10, 20, 1, 2, 3, 4, 5]);
}
}
#[cfg(test)]
mod test_closure {
use super::*;
#[test]
fn test_closure_implements_trait() {
let data = vec![1, 2, 3];
let closure = move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
};
let mut target = vec![0];
let old_len = closure.apply(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_closure_and_then() {
let data1 = vec![1, 2];
let data2 = [3, 4];
let chained = (move |x: &mut Vec<i32>| {
x.extend(data1);
x.len() })
.and_then(move |len: &usize| {
*len + data2.len()
});
let mut target = vec![0];
let final_len = chained.apply(&mut target);
assert_eq!(final_len, 5); assert_eq!(target, vec![0, 1, 2]);
}
#[test]
fn test_closure_map() {
let data = vec![1, 2, 3];
let mapped = (move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
})
.and_then::<String, _>(|old_len: &usize| format!("Old length: {}", *old_len));
let mut target = vec![0];
let result = mapped.apply(&mut target);
assert_eq!(result, "Old length: 1");
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_closure_into_box() {
let data = vec![1, 2, 3];
let closure = move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
};
let box_func = closure.into_box();
let mut target = vec![0];
let old_len = box_func.apply(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_closure_into_fn() {
let data = vec![1, 2, 3];
let closure = move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
};
let fn_closure = closure.into_fn();
let mut target = vec![0];
let old_len = fn_closure(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_closure_to_box() {
let data = vec![1, 2, 3];
let closure = move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
};
let box_func = closure.to_box();
let mut target = vec![0];
let old_len = box_func.apply(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_closure_to_fn() {
let data = vec![1, 2, 3];
let closure = move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
};
let fn_closure = closure.to_fn();
let mut target = vec![0];
let old_len = fn_closure(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_move_semantics() {
let data = vec![1, 2, 3];
let closure = move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data); old_len
};
let mut target = vec![0];
let old_len = closure.apply(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_into_box() {
let data = vec![1, 2, 3];
let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
});
let box_func = func.into_box();
let mut target = vec![0];
let old_len = box_func.apply(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
#[test]
fn test_into_fn() {
let data = vec![1, 2, 3];
let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
let old_len = x.len();
x.extend(data);
old_len
});
let closure = func.into_fn();
let mut target = vec![0];
let old_len = closure(&mut target);
assert_eq!(old_len, 1);
assert_eq!(target, vec![0, 1, 2, 3]);
}
}
#[test]
fn test_box_mutating_function_once_debug_display() {
let double = BoxMutatingFunctionOnce::new(|x: &mut i32| *x * 2);
let debug_str = format!("{:?}", double);
assert!(debug_str.contains("BoxMutatingFunctionOnce"));
assert!(debug_str.contains("name"));
assert!(debug_str.contains("function"));
let display_str = format!("{}", double);
assert_eq!(display_str, "BoxMutatingFunctionOnce");
let named_double =
BoxMutatingFunctionOnce::new_with_name("mutating_once_double", |x: &mut i32| *x * 2);
let named_debug_str = format!("{:?}", named_double);
assert!(named_debug_str.contains("BoxMutatingFunctionOnce"));
assert!(named_debug_str.contains("name"));
assert!(named_debug_str.contains("function"));
let named_display_str = format!("{}", named_double);
assert_eq!(
named_display_str,
"BoxMutatingFunctionOnce(mutating_once_double)"
);
}
#[test]
fn test_box_mutating_function_once_name_methods() {
let mut double =
BoxMutatingFunctionOnce::new_with_name("box_mutating_once_func", |x: &mut i32| {
*x *= 2;
*x
});
assert_eq!(double.name(), Some("box_mutating_once_func"));
double.set_name("modified_box_mutating_once");
assert_eq!(double.name(), Some("modified_box_mutating_once"));
let mut value = 5;
assert_eq!(double.apply(&mut value), 10);
assert_eq!(value, 10);
}
#[test]
fn test_box_conditional_mutating_function_once_debug_display() {
let double = BoxMutatingFunctionOnce::new(|x: &mut i32| *x * 2);
let conditional = double.when(|x: &i32| *x > 0);
let debug_str = format!("{:?}", conditional);
assert!(debug_str.contains("BoxConditionalMutatingFunctionOnce"));
assert!(debug_str.contains("name"));
assert!(debug_str.contains("function"));
assert!(debug_str.contains("predicate"));
let display_str = format!("{}", conditional);
assert!(display_str.starts_with("BoxConditionalMutatingFunctionOnce("));
assert!(display_str.contains("BoxMutatingFunctionOnce"));
assert!(display_str.contains("BoxPredicate"));
assert!(display_str.ends_with(")"));
let triple =
BoxMutatingFunctionOnce::new_with_name("triple_mutating_once_func", |x: &mut i32| *x * 3);
let named_conditional = triple.when(|x: &i32| *x % 2 == 0);
let named_debug_str = format!("{:?}", named_conditional);
assert!(named_debug_str.contains("BoxConditionalMutatingFunctionOnce"));
assert!(named_debug_str.contains("name"));
assert!(named_debug_str.contains("function"));
assert!(named_debug_str.contains("predicate"));
let named_display_str = format!("{}", named_conditional);
assert!(named_display_str.starts_with("BoxConditionalMutatingFunctionOnce("));
assert!(named_display_str.contains("BoxMutatingFunctionOnce(triple_mutating_once_func)"));
assert!(named_display_str.contains("BoxPredicate"));
assert!(named_display_str.ends_with(")"));
}
#[test]
fn test_custom_cloneable_mutating_function_once_to_box() {
#[derive(Clone, Debug)]
struct MyCloneableMutatingFunction {
multiplier: i32,
offset: i32,
}
impl MyCloneableMutatingFunction {
fn new(multiplier: i32, offset: i32) -> Self {
Self { multiplier, offset }
}
}
impl MutatingFunctionOnce<i32, i32> for MyCloneableMutatingFunction {
fn apply(self, input: &mut i32) -> i32 {
*input = *input * self.multiplier + self.offset;
*input
}
}
let func = MyCloneableMutatingFunction::new(2, 5);
let mut input1 = 3;
let boxed = func.to_box();
let result1 = boxed.apply(&mut input1);
assert_eq!(result1, 11); assert_eq!(input1, 11);
let mut input2 = 4;
let another_boxed = func.to_box();
let result2 = another_boxed.apply(&mut input2);
assert_eq!(result2, 13); assert_eq!(input2, 13);
let func_closure = func.to_fn();
let mut input3 = 2;
let result3 = func_closure(&mut input3);
assert_eq!(result3, 9); assert_eq!(input3, 9);
let mut input4 = 1;
let final_boxed = func.to_box();
let result4 = final_boxed.apply(&mut input4);
assert_eq!(result4, 7); assert_eq!(input4, 7);
}