1use core::{fmt, marker::PhantomData};
2use tracing::error;
3
4use serde::{Deserialize, Serialize};
5
6use crate::{
7 dataformat::DataFormat,
8 request::Request,
9 response::{HandlerResponse, Response},
10 RpcError, RpcResult,
11};
12
13const ERR_FAILED_TO_PARSE: &str = "Failed to parse RPC request";
14
15#[allow(clippy::module_name_repetitions)]
17pub struct RpcServer<'a, RPC: RpcServerHandler<'a>, M, SRC, R> {
18 _phantom_a: PhantomData<&'a ()>,
19 _phantom_m: PhantomData<M>,
20 _phantom_src: PhantomData<SRC>,
21 _phantom_r: PhantomData<R>,
22 rpc: RPC,
23}
24
25impl<'a, RPC: RpcServerHandler<'a, Method = M, Result = R, Source = SRC>, M, SRC, R>
26 RpcServer<'a, RPC, M, SRC, R>
27where
28 M: Deserialize<'a> + 'a,
29 R: Serialize + Deserialize<'a> + 'a,
30 SRC: fmt::Display,
31{
32 pub fn new(rpc: RPC) -> Self {
34 Self {
35 _phantom_a: PhantomData,
36 _phantom_m: PhantomData,
37 _phantom_src: PhantomData,
38 _phantom_r: PhantomData,
39 rpc,
40 }
41 }
42 pub fn handle_request(&'a self, request: Request<M>, source: SRC) -> Option<Response<R>> {
44 let result = match self.rpc.handle_call(request.method, source) {
45 Ok(v) => HandlerResponse::Ok(v),
46 Err(e) => HandlerResponse::Err(RpcError {
47 kind: e.kind,
48 message: e.message,
49 }),
50 };
51 request
52 .id
53 .map(move |id| Response::from_handler_response(id, result))
54 }
55 pub fn handle_request_payload<D>(&'a self, payload: &'a [u8], source: SRC) -> Option<Vec<u8>>
57 where
58 D: DataFormat,
59 {
60 macro_rules! serialize_response {
61 ($response:expr) => {{
62 match D::pack(&$response) {
63 Ok(v) => Some(v),
64 Err(error) => {
65 error!(%error, "Failed to serialize response");
66 if let Ok(response) = D::pack(
67 &Response::<R>::from_server_error(
68 $response.id().clone(), error.to_string())) {
69 Some(response)
70 } else {
71 None
72 }
73 }
74 }
75 }};
76 }
77 match D::unpack::<Request<M>>(payload) {
78 Ok(req) => self
79 .handle_request(req, source)
80 .and_then(|response| serialize_response!(response)),
81 Err(error) => {
82 error!(%source, %error, ERR_FAILED_TO_PARSE);
83 if let Ok(invalid) = D::unpack::<crate::request::InvalidRequest>(payload) {
84 invalid
85 .into_response(error.to_string())
86 .and_then(|response: Response<R>| serialize_response!(response))
87 } else {
88 None
89 }
90 }
91 }
92 }
93}
94
95#[allow(clippy::module_name_repetitions)]
97pub trait RpcServerHandler<'a> {
98 type Method: Deserialize<'a>;
100 type Result: Serialize + Deserialize<'a>;
102 type Source;
104
105 fn handle_call(&'a self, method: Self::Method, source: Self::Source)
107 -> RpcResult<Self::Result>;
108}