1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use crate::RpcResources;

/// Macro generatring the RpcHandler implementations for zero or more FromRpcResources with the last argument being IntoRpcParams
/// and one with not last IntoRpcParams argument.
#[macro_export]
macro_rules! impl_rpc_handler_pair {
    ($K:ty, $($T:ident),*) => {

		// RpcHandler implementations for zero or more FromRpcResources with the last argument being IntoRpcParams
        impl<F, Fut, $($T,)* P, R, E> $crate::RpcHandler<($($T,)*), (P,), R> for F
        where
            F: FnOnce($($T,)* P) -> Fut + Clone + Send + 'static,
            $( $T: $crate::FromRpcResources+ Clone + Send + Sync + 'static, )*
            P: $crate::IntoRpcParams + Send + Sync + 'static,
            R: serde::Serialize + Send + Sync + 'static,
            E: $crate::IntoRpcHandlerError,
            Fut: futures::Future<Output = core::result::Result<R, E>> + Send,
        {
            type Future = $crate::handler::PinFutureValue;

						#[allow(unused)] // somehow resources will be marked as unused
            fn call(
                self,
                resources: RpcResources,
                params_value: Option<serde_json::Value>,
            ) -> Self::Future {
                Box::pin(async move {
                    let param = P::into_params(params_value)?;

                    let res = self(
                        $( $T::from_resources(&resources)?, )*
                        param,
                    ).await;

                    match res {
                        Ok(result) => Ok(serde_json::to_value(result)?),
                        Err(ex) => todo!(),
                    }
                })
            }
        }

       // RpcHandler implementations for zero or more FromRpcResources and NO IntoRpcParams
       impl<F, Fut, $($T,)* R, E> $crate::RpcHandler<($($T,)*), (), R> for F
       where
               F: FnOnce($($T,)*) -> Fut + Clone + Send + 'static,
               $( $T: $crate::FromRpcResources + Clone + Send + Sync + 'static, )*
               R: serde::Serialize + Send + Sync + 'static,
               E: $crate::IntoRpcHandlerError,
               Fut: futures::Future<Output = core::result::Result<R, E>> + Send,
       {
               type Future = $crate::handler::PinFutureValue;

               #[allow(unused)] // somehow resources will be marked as unused
               fn call(
                       self,
                       resources: RpcResources,
                       _params: Option<serde_json::Value>,
               ) -> Self::Future {
                       Box::pin(async move {
                            let res = self(
                                    $( $T::from_resources(&resources)?, )*
                            ).await;

                            match res {
                                Ok(result) => Ok(serde_json::to_value(result)?),
                                Err(ex) => todo!(),
                            }

                       })
               }
       }
    };

}

impl_rpc_handler_pair!(RpcResources,);
impl_rpc_handler_pair!(RpcResources, T1);
impl_rpc_handler_pair!(RpcResources, T1, T2);
impl_rpc_handler_pair!(RpcResources, T1, T2, T3);
impl_rpc_handler_pair!(RpcResources, T1, T2, T3, T4);
impl_rpc_handler_pair!(RpcResources, T1, T2, T3, T4, T5);