1pub fn call_compensation_function<In, Out, Err>(
16 f: impl CompensationFunction<In, Out, Err>,
17 result: impl TupleOrUnit<Out>,
18 input: impl TupleOrUnit<In>,
19) -> Result<(), Err> {
20 f.call(result, input)
21}
22
23pub trait TupleOrUnit<T> {
24 fn into(self) -> T;
25}
26
27pub trait CompensationFunction<In, Out, Err> {
28 fn call(self, result: impl TupleOrUnit<Out>, input: impl TupleOrUnit<In>) -> Result<(), Err>;
29}
30
31impl<F, Err> CompensationFunction<(), (), (Err,)> for F
32where
33 F: FnOnce() -> Result<(), Err>,
34{
35 fn call(
36 self,
37 _result: impl TupleOrUnit<()>,
38 _input: impl TupleOrUnit<()>,
39 ) -> Result<(), (Err,)> {
40 self().map_err(|e| (e,))?;
41 Ok(())
42 }
43}
44
45impl<F, Out, Err> CompensationFunction<(), (Out,), (Err,)> for F
46where
47 F: FnOnce(Out) -> Result<(), Err>,
48{
49 fn call(
50 self,
51 out: impl TupleOrUnit<(Out,)>,
52 _input: impl TupleOrUnit<()>,
53 ) -> Result<(), (Err,)> {
54 let (out,) = out.into();
55 self(out).map_err(|err| (err,))
56 }
57}
58
59impl<T> TupleOrUnit<()> for T {
60 fn into(self) {}
61}
62
63macro_rules! compensation_function {
64 ($($ty:ident),*) => {
65 impl<F, $($ty),*, Out, Err> CompensationFunction<($($ty),*,), (Out,), (Err,)> for F
66 where
67 F: FnOnce(Out, $($ty),*) -> Result<(), Err>,
68 {
69 fn call(
70 self,
71 out: impl TupleOrUnit<(Out,)>,
72 input: impl TupleOrUnit<($($ty),*,)>,
73 ) -> Result<(), (Err,)> {
74 #[allow(non_snake_case)]
75 let ( $($ty,)+ ) = input.into();
76 let (out,) = out.into();
77 self(out, $($ty),*).map_err(|err| (err,))
78 }
79 }
80 }
81}
82
83macro_rules! tuple_or_unit {
84 ($($ty:ident),*) => {
85 impl<$($ty),*> TupleOrUnit<($($ty,)*)> for ($($ty,)*) {
86 fn into(self) -> ($($ty,)*) {
87 self
88 }
89 }
90 }
91}
92
93macro_rules! generate_for_tuples {
94 ($name:ident) => {
95 $name!(T1);
96 $name!(T1, T2);
97 $name!(T1, T2, T3);
98 $name!(T1, T2, T3, T4);
99 $name!(T1, T2, T3, T4, T5);
100 $name!(T1, T2, T3, T4, T5, T6);
101 $name!(T1, T2, T3, T4, T5, T6, T7);
102 $name!(T1, T2, T3, T4, T5, T6, T7, T8);
103 $name!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
104 $name!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
105 $name!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
106 $name!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
107 $name!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
108 $name!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
109 $name!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
110 $name!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
111 };
112}
113
114generate_for_tuples!(tuple_or_unit);
115generate_for_tuples!(compensation_function);