roboplc_rpc/
response.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    de_validate_version, serialize_version, Id, RpcError, RpcErrorKind, RpcResult, String,
5    VERSION_HEADER,
6};
7
8#[derive(Serialize, Deserialize, Debug)]
9#[serde(deny_unknown_fields)]
10/// JSON-RPC Response object
11pub struct Response<R> {
12    #[serde(
13        default,
14        deserialize_with = "de_validate_version",
15        serialize_with = "serialize_version",
16        skip_serializing_if = "Option::is_none"
17    )]
18    jsonrpc: Option<()>,
19    #[cfg_attr(feature = "canonical", serde(alias = "i"))]
20    #[cfg_attr(not(feature = "canonical"), serde(rename = "i"))]
21    id: Id,
22    #[cfg_attr(feature = "std", serde(flatten))]
23    #[cfg_attr(not(feature = "std"), serde(rename = "p"))]
24    handler_response: HandlerResponse<R>,
25}
26
27impl<R> Response<R> {
28    /// Split the Response object into its parts (useful for 3rd party serialization)
29    pub fn into_parts(self) -> (Id, HandlerResponse<R>) {
30        (self.id, self.handler_response)
31    }
32    /// Combine the parts into a Response object (useful for 3rd party de-serialization)
33    pub fn from_parts(id: Id, handler_response: HandlerResponse<R>) -> Response<R> {
34        Response {
35            jsonrpc: VERSION_HEADER,
36            id,
37            handler_response,
38        }
39    }
40    /// Create a new Response object with the given ID and result from the RPC handler response
41    pub fn from_handler_response(id: Id, handler_response: HandlerResponse<R>) -> Response<R> {
42        Response {
43            jsonrpc: VERSION_HEADER,
44            id,
45            handler_response,
46        }
47    }
48    /// Convert the response into an error response with the given error
49    pub fn into_error_response(self, rpc_error: RpcError) -> Response<R> {
50        Response {
51            jsonrpc: VERSION_HEADER,
52            id: self.id,
53            handler_response: HandlerResponse::Err(rpc_error),
54        }
55    }
56    /// Get the ID of the response
57    pub fn id(&self) -> &Id {
58        &self.id
59    }
60    /// Get the handler response
61    pub fn into_server_error_response(self, error: String) -> Response<R> {
62        Self::from_server_error(self.id, error)
63    }
64    /// Create a new Response object with the given ID and error message
65    pub fn from_server_error(id: Id, error: String) -> Response<R> {
66        Response {
67            jsonrpc: VERSION_HEADER,
68            id,
69            handler_response: HandlerResponse::Err(RpcError {
70                kind: RpcErrorKind::InternalError,
71                message: Some(error),
72            }),
73        }
74    }
75}
76
77#[allow(clippy::module_name_repetitions)]
78#[derive(Serialize, Deserialize, Debug)]
79#[serde(deny_unknown_fields)]
80/// RPC handler response object. Basically duplicates the standard Result object, required for the
81/// proper serialization
82pub enum HandlerResponse<R> {
83    #[cfg_attr(feature = "canonical", serde(rename = "result", alias = "r"))]
84    #[cfg_attr(not(feature = "canonical"), serde(rename = "r"))]
85    /// The RPC handler returned a data
86    Ok(R),
87    #[cfg_attr(feature = "canonical", serde(rename = "error", alias = "e"))]
88    #[cfg_attr(not(feature = "canonical"), serde(rename = "e"))]
89    /// The RPC handler returned an error
90    Err(RpcError),
91}
92
93impl<R> HandlerResponse<R> {
94    /// Is the response Ok
95    pub fn is_ok(&self) -> bool {
96        matches!(self, HandlerResponse::Ok(_))
97    }
98    /// Is the response an error
99    pub fn is_err(&self) -> bool {
100        matches!(self, HandlerResponse::Err(_))
101    }
102    /// Convert the response data into an option
103    pub fn ok(&self) -> Option<&R> {
104        match self {
105            HandlerResponse::Ok(r) => Some(r),
106            HandlerResponse::Err(_) => None,
107        }
108    }
109    /// Convert the response error into an option
110    pub fn err(&self) -> Option<&RpcError> {
111        match self {
112            HandlerResponse::Ok(_) => None,
113            HandlerResponse::Err(e) => Some(e),
114        }
115    }
116}
117
118impl<R> From<HandlerResponse<R>> for RpcResult<R> {
119    fn from(res: HandlerResponse<R>) -> Self {
120        match res {
121            HandlerResponse::Err(e) => Err(RpcError {
122                kind: e.kind,
123                message: e.message,
124            }),
125            HandlerResponse::Ok(r) => Ok(r),
126        }
127    }
128}
129
130impl<R> From<RpcResult<R>> for HandlerResponse<R> {
131    fn from(res: RpcResult<R>) -> Self {
132        match res {
133            Ok(r) => HandlerResponse::Ok(r),
134            Err(e) => HandlerResponse::Err(e),
135        }
136    }
137}