1use std::borrow::Cow;
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5use crate::Id;
6
7#[derive(Debug, Clone)]
9pub struct Response<'a, T, E> {
10 pub result: Result<T, Error<'a, E>>,
12 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#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
45pub struct ErrorCode(pub i64);
46
47impl ErrorCode {
48 pub const PARSE_ERROR: ErrorCode = ErrorCode(-32700);
50 pub const INVALID_REQUEST: ErrorCode = ErrorCode(-32600);
52 pub const METHOD_NOT_FOUND: ErrorCode = ErrorCode(-32601);
54 pub const INVALID_PARAMS: ErrorCode = ErrorCode(-32602);
56 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#[derive(Debug, Clone)]
76pub struct Error<'a, E> {
77 pub code: ErrorCode,
79 pub message: Cow<'a, str>,
81 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 #[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}