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