1use core::marker::PhantomData;
2
3pub struct FnMutant<In, Extra, Out, F: for<'a> Fn(In, Extra) -> Out> {
4 pub f: F,
5 phantom_in: PhantomData<In>,
6 phantom_extra: PhantomData<Extra>,
7 phantom_out: PhantomData<Out>,
8}
9
10impl<In, Extra, Out, F: for<'a> Fn(In, Extra) -> Out> FnMutant<In, Extra, Out, F> {
11 pub fn new(f: F) -> Self {
12 Self {
13 f,
14 phantom_in: PhantomData,
15 phantom_extra: PhantomData,
16 phantom_out: PhantomData,
17 }
18 }
19}
20
21pub fn mutant<In, Extra, Out, F: for<'a> Fn(In, Extra) -> Out>(
22 f: F,
23) -> FnMutant<In, Extra, Out, F> {
24 FnMutant::new(f)
25}
26
27#[cfg(test)]
28mod tests {
29 use std::iter::FromIterator;
30 use crate::FnMutant;
31
32 fn incr(x: &mut i32, amount: i32) {
33 *x += amount
35 }
36
37 fn decr(x: &mut i32, amount: i32) {
38 *x -= amount
39 }
40
41
42 fn helper(fps: &[FnMutant<&mut i32, i32, (), &dyn for<'b> Fn(&mut i32, i32)>],
43 xs: &mut [i32], expect: Vec<i32>) {
44 let len = xs.len();
45 for i in 0..len * 5 {
46 for fp in fps {
47 (fp.f)(xs.get_mut(i % len).unwrap(), 1);
48 }
49 }
50 assert_eq!(xs, expect.as_slice());
51 }
52
53 #[test]
54 fn it_works() {
55 use super::*;
56 let fps: [FnMutant<&mut i32, i32, (), &dyn for<'b> Fn(&mut i32, i32)>; 3] =
57 [mutant(&incr), mutant(&decr), mutant(&incr)];
58 {
59 let mut xs = [0, 1, 2, 3, 4, 5];
60 let expect = Vec::from_iter(xs.iter().map(|x| x + 5));
61 helper(&fps, &mut xs, expect.clone());
62 assert_eq!(xs, expect.as_slice());
63 drop(xs);
64 }
65 {
66 let mut xs = [0, 1, 2, 3, 4, 5];
67 let expect = Vec::from_iter(xs.iter().map(|x| x + 5));
68 helper(&fps, &mut xs, expect.clone());
69 assert_eq!(xs, expect.as_slice());
70 drop(xs);
71 }
72 }
73}