rpc_router/handler/
handler_wrapper.rs

1use crate::Handler;
2use crate::handler::PinFutureValue;
3use crate::{Resources, Result};
4use futures::Future;
5use serde_json::Value;
6use std::marker::PhantomData;
7use std::pin::Pin;
8
9/// `RpcHandlerWrapper` is an `RpcHandler` wrapper that implements
10/// `RpcHandlerWrapperTrait` for type erasure, enabling dynamic dispatch.
11/// Generics:
12/// - `H`: The handler trait for the function
13/// - `K`: The Resources, meaning the type passed in the call that has the `FromResources` trait for the various `T` types (cannot use `R`, as it is reserved for the
14/// - `T`: The type (can be a tuple when multiple) for the function parameters
15/// - `P`: The JSON RPC parameter
16/// - `R`: The response type
17///
18/// Thus, all these types except `H` will match the generic of the `H` handler trait. We keep them in phantom data.
19#[derive(Clone)]
20pub struct RpcHandlerWrapper<H, T, P, R> {
21	handler: H,
22	_marker: PhantomData<(T, P, R)>,
23}
24
25// Constructor
26impl<H, T, P, R> RpcHandlerWrapper<H, T, P, R> {
27	pub fn new(handler: H) -> Self {
28		Self {
29			handler,
30			_marker: PhantomData,
31		}
32	}
33}
34
35// Call Impl
36impl<H, T, P, R> RpcHandlerWrapper<H, T, P, R>
37where
38	H: Handler<T, P, R> + Send + Sync + 'static,
39	T: Send + Sync + 'static,
40	P: Send + Sync + 'static,
41	R: Send + Sync + 'static,
42{
43	pub fn call(&self, rpc_resources: Resources, params: Option<Value>) -> H::Future {
44		// Note: Since handler is a FnOnce, we can use it only once, so we clone it.
45		//       This is likely optimized by the compiler.
46		let handler = self.handler.clone();
47		Handler::call(handler, rpc_resources, params)
48	}
49}
50
51/// `RpcHandlerWrapperTrait` enables `RpcHandlerWrapper` to become a trait object,
52/// allowing for dynamic dispatch.
53pub trait RpcHandlerWrapperTrait: Send + Sync {
54	fn call(&self, rpc_resources: Resources, params: Option<Value>) -> PinFutureValue;
55}
56
57impl<H, T, P, R> RpcHandlerWrapperTrait for RpcHandlerWrapper<H, T, P, R>
58where
59	H: Handler<T, P, R> + Clone + Send + Sync + 'static,
60	T: Send + Sync + 'static,
61	P: Send + Sync + 'static,
62	R: Send + Sync + 'static,
63{
64	fn call(
65		&self,
66		rpc_resources: Resources,
67		params: Option<Value>,
68	) -> Pin<Box<dyn Future<Output = Result<Value>> + Send>> {
69		Box::pin(self.call(rpc_resources, params))
70	}
71}