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
use axum::response::{IntoResponse, Response};
use protobuf::MessageFull;

use crate::error::{RpcError, RpcErrorCode, RpcIntoError};

pub type RpcResult<T> = Result<T, RpcError>;

pub struct RpcResponse<T> {
    pub(crate) response: RpcResult<T>,
    pub(crate) parts: Response,
}

impl<T> IntoResponse for RpcResponse<T>
where
    T: MessageFull,
{
    fn into_response(self) -> Response {
        let rpc_call_response: Response = {
            match self.response {
                Ok(value) => protobuf_json_mapping::print_to_string(&value)
                    .map_err(|_e| {
                        RpcError::new(
                            RpcErrorCode::Internal,
                            "Failed to serialize response".to_string(),
                        )
                    })
                    .into_response(),
                Err(e) => e.into_response(),
            }
        };

        let (parts, _) = self.parts.into_parts();
        (parts, rpc_call_response).into_response()
    }
}

pub trait RpcIntoResponse<T>: Send + Sync + 'static
where
    T: MessageFull,
{
    fn rpc_into_response(self) -> RpcResponse<T>;
}

impl<T> RpcIntoResponse<T> for T
where
    T: MessageFull,
{
    fn rpc_into_response(self) -> RpcResponse<T> {
        RpcResponse {
            response: Ok(self),
            parts: Response::default(),
        }
    }
}

impl<T, E> RpcIntoResponse<T> for Result<T, E>
where
    T: MessageFull,
    E: RpcIntoError + Send + Sync + 'static,
{
    fn rpc_into_response(self) -> RpcResponse<T> {
        match self {
            Ok(res) => res.rpc_into_response(),
            Err(err) => err.rpc_into_error().rpc_into_response(),
        }
    }
}