jsonrpc_sys/
response.rs

1use std::borrow::Cow;
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5use crate::Id;
6
7/// A JSON-RPC 2.0 response.
8#[derive(Debug, Clone)]
9pub struct Response<'a, T, E> {
10    /// The outcome of the request.
11    pub result: Result<T, Error<'a, E>>,
12    /// The ID of the request to which this repsonse is a reply.
13    pub id: Id<'a>,
14}
15
16impl<'a, T, E> Serialize for Response<'a, T, E>
17where
18    T: Serialize,
19    E: Serialize,
20{
21    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
22    where
23        S: Serializer,
24    {
25        OutogingResponse::from_response(self).serialize(serializer)
26    }
27}
28
29impl<'de, 'a, T, E> Deserialize<'de> for Response<'a, T, E>
30where
31    'de: 'a,
32    T: Deserialize<'de>,
33    E: Deserialize<'de>,
34{
35    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
36    where
37        D: Deserializer<'de>,
38    {
39        IncomingResponse::deserialize(deserializer).and_then(IncomingResponse::into_response)
40    }
41}
42
43/// A JSON-RPC 2.0 error code.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
45pub struct ErrorCode(pub i64);
46
47impl ErrorCode {
48    /// The error code returned when the server cannot parsed the request.
49    pub const PARSE_ERROR: ErrorCode = ErrorCode(-32700);
50    /// The error code returned when the request is not a valid JSON-RPC 2.0 request.
51    pub const INVALID_REQUEST: ErrorCode = ErrorCode(-32600);
52    /// The error code returned when the method does not exist.
53    pub const METHOD_NOT_FOUND: ErrorCode = ErrorCode(-32601);
54    /// The error code returned when the parameters are invalid.
55    pub const INVALID_PARAMS: ErrorCode = ErrorCode(-32602);
56    /// The error code returned when an internal error occurs.
57    pub const INTERNAL_ERROR: ErrorCode = ErrorCode(-32603);
58}
59
60impl From<i64> for ErrorCode {
61    #[inline(always)]
62    fn from(code: i64) -> Self {
63        Self(code)
64    }
65}
66
67impl From<ErrorCode> for i64 {
68    #[inline(always)]
69    fn from(code: ErrorCode) -> Self {
70        code.0
71    }
72}
73
74/// A JSON-RPC 2.0 error.
75#[derive(Debug, Clone)]
76pub struct Error<'a, E> {
77    /// The error code.
78    pub code: ErrorCode,
79    /// The error message.
80    pub message: Cow<'a, str>,
81    /// Additional data about the error.
82    pub data: Option<E>,
83}
84
85#[derive(Serialize)]
86struct OutogingResponse<'a, T, E> {
87    jsonrpc: &'a str,
88    #[serde(skip_serializing_if = "Option::is_none")]
89    result: Option<&'a T>,
90    #[serde(skip_serializing_if = "Option::is_none")]
91    error: Option<OutgoingError<'a, E>>,
92    id: crate::Id<'a>,
93}
94
95impl<'a, T, E> OutogingResponse<'a, T, E> {
96    fn from_response(response: &'a crate::Response<T, E>) -> Self {
97        let (result, error) = match response.result {
98            Ok(ref result) => (Some(result), None),
99            Err(ref error) => (
100                None,
101                Some(OutgoingError {
102                    code: error.code.0,
103                    message: &error.message,
104                    data: error.data.as_ref(),
105                }),
106            ),
107        };
108
109        Self {
110            jsonrpc: "2.0",
111            result,
112            error,
113            id: id_as_ref(&response.id),
114        }
115    }
116}
117
118#[derive(Serialize)]
119struct OutgoingError<'a, E> {
120    code: i64,
121    message: &'a str,
122    #[serde(skip_serializing_if = "Option::is_none")]
123    data: Option<&'a E>,
124}
125
126#[derive(Deserialize)]
127struct IncomingResponse<'a, T, E> {
128    #[serde(borrow)]
129    jsonrpc: Cow<'a, str>,
130    #[serde(default = "Option::default")]
131    result: Option<T>,
132    #[serde(default = "Option::default", borrow)]
133    error: Option<IncomingError<'a, E>>,
134    // The option is there to represent the `null` value. The `id` field must still be
135    // present.
136    #[serde(borrow)]
137    id: crate::Id<'a>,
138}
139
140impl<'a, T, E> IncomingResponse<'a, T, E> {
141    fn into_response<Er>(self) -> Result<crate::Response<'a, T, E>, Er>
142    where
143        Er: serde::de::Error,
144    {
145        if self.jsonrpc != "2.0" {
146            return Err(Er::invalid_value(
147                serde::de::Unexpected::Str(&self.jsonrpc),
148                &"2.0",
149            ));
150        }
151
152        let result = match (self.result, self.error) {
153            (Some(result), None) => Ok(result),
154            (None, Some(error)) => Err(crate::Error {
155                code: crate::ErrorCode(error.code),
156                message: error.message,
157                data: error.data,
158            }),
159            (Some(_), Some(_)) => {
160                return Err(Er::custom(
161                    "response cannot contain both `result` and `error` fields",
162                ))
163            }
164            (None, None) => {
165                return Err(Er::custom(
166                    "response must contain either `result` or `error` field",
167                ))
168            }
169        };
170
171        Ok(crate::Response {
172            result,
173            id: self.id,
174        })
175    }
176}
177
178#[derive(Deserialize)]
179struct IncomingError<'a, E> {
180    code: i64,
181    #[serde(borrow)]
182    message: Cow<'a, str>,
183    #[serde(default = "Option::default")]
184    data: Option<E>,
185}
186
187fn id_as_ref<'a>(id: &'a crate::Id) -> crate::Id<'a> {
188    match *id {
189        crate::Id::Null => crate::Id::Null,
190        crate::Id::Float(f) => crate::Id::Float(f),
191        crate::Id::Str(ref s) => crate::Id::Str(Cow::Borrowed(s)),
192        crate::Id::Int(i) => crate::Id::Int(i),
193        crate::Id::Uint(u) => crate::Id::Uint(u),
194    }
195}