1use std::borrow::Cow as StdCow;
30use std::fmt;
31use std::marker::PhantomData;
32
33use crate::error::ErrorCode;
34use crate::params::{Id, SubscriptionId, TwoPointZero};
35use crate::request::Notification;
36use crate::{ErrorObject, ErrorObjectOwned};
37use serde::ser::SerializeStruct;
38use serde::{Deserialize, Deserializer, Serialize, Serializer};
39
40pub struct Response<'a, T: Clone> {
42 pub jsonrpc: Option<TwoPointZero>,
44 pub payload: ResponsePayload<'a, T>,
46 pub id: Id<'a>,
48}
49
50impl<'a, T: Clone> Response<'a, T> {
51 pub fn new(payload: ResponsePayload<'a, T>, id: Id<'a>) -> Response<'a, T> {
53 Response { jsonrpc: Some(TwoPointZero), payload, id }
54 }
55
56 pub fn into_owned(self) -> Response<'static, T> {
58 Response { jsonrpc: self.jsonrpc, payload: self.payload.into_owned(), id: self.id.into_owned() }
59 }
60}
61
62impl<'a, T> fmt::Display for Response<'a, T>
63where
64 T: Serialize + Clone,
65{
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 f.write_str(&serde_json::to_string(&self).expect("valid JSON; qed"))
68 }
69}
70
71impl<'a, T> fmt::Debug for Response<'a, T>
72where
73 T: Serialize + Clone,
74{
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 f.write_str(&serde_json::to_string(&self).expect("valid JSON; qed"))
77 }
78}
79
80#[derive(Debug)]
83pub struct Success<'a, T> {
84 pub jsonrpc: Option<TwoPointZero>,
86 pub result: T,
88 pub id: Id<'a>,
90}
91
92impl<'a, T: Clone> TryFrom<Response<'a, T>> for Success<'a, T> {
93 type Error = ErrorObjectOwned;
94
95 fn try_from(rp: Response<'a, T>) -> Result<Self, Self::Error> {
96 match rp.payload {
97 ResponsePayload::Error(e) => Err(e.into_owned()),
98 ResponsePayload::Success(r) => Ok(Success { jsonrpc: rp.jsonrpc, result: r.into_owned(), id: rp.id }),
99 }
100 }
101}
102
103#[derive(Serialize, Deserialize, Debug)]
105pub struct SubscriptionPayload<'a, T> {
106 #[serde(borrow)]
108 pub subscription: SubscriptionId<'a>,
109 pub result: T,
111}
112
113pub type SubscriptionResponse<'a, T> = Notification<'a, SubscriptionPayload<'a, T>>;
115pub type SubscriptionError<'a, T> = Notification<'a, SubscriptionPayloadError<'a, T>>;
117
118#[derive(Serialize, Deserialize, Debug)]
120pub struct SubscriptionPayloadError<'a, T> {
121 #[serde(borrow)]
123 pub subscription: SubscriptionId<'a>,
124 pub error: T,
126}
127
128#[derive(Debug, Clone, PartialEq)]
137pub enum ResponsePayload<'a, T>
138where
139 T: Clone,
140{
141 Success(StdCow<'a, T>),
143 Error(ErrorObject<'a>),
145}
146
147impl<'a, T: Clone> ResponsePayload<'a, T> {
148 pub fn success(t: T) -> Self {
150 Self::Success(StdCow::Owned(t))
151 }
152
153 pub fn success_borrowed(t: &'a T) -> Self {
155 Self::Success(StdCow::Borrowed(t))
156 }
157
158 pub fn into_owned(self) -> ResponsePayload<'static, T> {
160 match self {
161 Self::Error(e) => ResponsePayload::Error(e.into_owned()),
162 Self::Success(r) => ResponsePayload::Success(StdCow::Owned(r.into_owned())),
163 }
164 }
165
166 pub fn error(e: impl Into<ErrorObjectOwned>) -> Self {
168 Self::Error(e.into())
169 }
170
171 pub fn error_borrowed(e: impl Into<ErrorObject<'a>>) -> Self {
173 Self::Error(e.into())
174 }
175}
176
177impl<'a, T: Clone> From<ErrorCode> for ResponsePayload<'a, T> {
178 fn from(code: ErrorCode) -> ResponsePayload<'a, T> {
179 Self::Error(code.into())
180 }
181}
182
183impl<'de, T> Deserialize<'de> for Response<'de, T>
184where
185 T: Deserialize<'de> + Clone,
186{
187 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
188 where
189 D: Deserializer<'de>,
190 T: Deserialize<'de> + Clone,
191 {
192 #[derive(Debug)]
193 enum Field {
194 Jsonrpc,
195 Result,
196 Error,
197 Id,
198 Ignore,
199 }
200
201 impl<'de> Deserialize<'de> for Field {
202 fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
203 where
204 D: Deserializer<'de>,
205 {
206 struct FieldVisitor;
207
208 impl<'de> serde::de::Visitor<'de> for FieldVisitor {
209 type Value = Field;
210
211 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
212 formatter.write_str("`jsonrpc`, `result`, `error` and `id`")
213 }
214
215 fn visit_str<E>(self, value: &str) -> Result<Field, E>
216 where
217 E: serde::de::Error,
218 {
219 match value {
220 "jsonrpc" => Ok(Field::Jsonrpc),
221 "result" => Ok(Field::Result),
222 "error" => Ok(Field::Error),
223 "id" => Ok(Field::Id),
224 _ => Ok(Field::Ignore),
225 }
226 }
227 }
228 deserializer.deserialize_identifier(FieldVisitor)
229 }
230 }
231
232 struct Visitor<T>(PhantomData<T>);
233
234 impl<T> Visitor<T> {
235 fn new() -> Visitor<T> {
236 Visitor(PhantomData)
237 }
238 }
239
240 impl<'de, T> serde::de::Visitor<'de> for Visitor<T>
241 where
242 T: Deserialize<'de> + Clone + 'de,
243 {
244 type Value = Response<'de, T>;
245
246 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
247 formatter.write_str("struct Response")
248 }
249
250 fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
251 where
252 V: serde::de::MapAccess<'de>,
253 {
254 let mut jsonrpc = None;
255 let mut result = None;
256 let mut error = None;
257 let mut id = None;
258 while let Some(key) = map.next_key()? {
259 match key {
260 Field::Result => {
261 if result.is_some() {
262 return Err(serde::de::Error::duplicate_field("result"));
263 }
264 result = Some(map.next_value()?);
265 }
266 Field::Error => {
267 if error.is_some() {
268 return Err(serde::de::Error::duplicate_field("error"));
269 }
270 error = Some(map.next_value()?);
271 }
272 Field::Id => {
273 if id.is_some() {
274 return Err(serde::de::Error::duplicate_field("id"));
275 }
276 id = Some(map.next_value()?);
277 }
278 Field::Jsonrpc => {
279 if jsonrpc.is_some() {
280 return Err(serde::de::Error::duplicate_field("jsonrpc"));
281 }
282 jsonrpc = Some(map.next_value()?);
283 }
284 Field::Ignore => {
285 let _ = map.next_value::<serde::de::IgnoredAny>()?;
286 }
287 }
288 }
289
290 let id = id.ok_or_else(|| serde::de::Error::missing_field("id"))?;
291
292 let response = match (jsonrpc, result, error) {
293 (_, Some(_), Some(_)) => {
294 return Err(serde::de::Error::duplicate_field("result and error are mutually exclusive"))
295 }
296 (Some(jsonrpc), Some(result), None) => {
297 Response { jsonrpc, payload: ResponsePayload::Success(result), id }
298 }
299 (Some(jsonrpc), None, Some(err)) => Response { jsonrpc, payload: ResponsePayload::Error(err), id },
300 (None, Some(result), _) => {
301 Response { jsonrpc: None, payload: ResponsePayload::Success(result), id }
302 }
303 (None, _, Some(err)) => Response { jsonrpc: None, payload: ResponsePayload::Error(err), id },
304 (_, None, None) => return Err(serde::de::Error::missing_field("result/error")),
305 };
306
307 Ok(response)
308 }
309 }
310
311 const FIELDS: &[&str] = &["jsonrpc", "result", "error", "id"];
312 deserializer.deserialize_struct("Response", FIELDS, Visitor::new())
313 }
314}
315
316impl<'a, T> Serialize for Response<'a, T>
317where
318 T: Serialize + Clone,
319{
320 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
321 where
322 S: Serializer,
323 {
324 let mut s = serializer.serialize_struct("Response", 3)?;
325
326 if let Some(field) = &self.jsonrpc {
327 s.serialize_field("jsonrpc", field)?;
328 }
329
330 s.serialize_field("id", &self.id)?;
331
332 match &self.payload {
333 ResponsePayload::Error(err) => s.serialize_field("error", err)?,
334 ResponsePayload::Success(r) => s.serialize_field("result", r)?,
335 };
336
337 s.end()
338 }
339}
340
341#[cfg(test)]
342mod tests {
343 use super::{Id, Response, TwoPointZero};
344 use crate::{response::ResponsePayload, ErrorObjectOwned};
345
346 #[test]
347 fn serialize_call_ok_response() {
348 let ser = serde_json::to_string(&Response {
349 jsonrpc: Some(TwoPointZero),
350 payload: ResponsePayload::success("ok"),
351 id: Id::Number(1),
352 })
353 .unwrap();
354 let exp = r#"{"jsonrpc":"2.0","id":1,"result":"ok"}"#;
355 assert_eq!(ser, exp);
356 }
357
358 #[test]
359 fn serialize_call_err_response() {
360 let ser = serde_json::to_string(&Response {
361 jsonrpc: Some(TwoPointZero),
362 payload: ResponsePayload::<()>::error(ErrorObjectOwned::owned(1, "lo", None::<()>)),
363 id: Id::Number(1),
364 })
365 .unwrap();
366 let exp = r#"{"jsonrpc":"2.0","id":1,"error":{"code":1,"message":"lo"}}"#;
367 assert_eq!(ser, exp);
368 }
369
370 #[test]
371 fn serialize_call_response_missing_version_field() {
372 let ser = serde_json::to_string(&Response {
373 jsonrpc: None,
374 payload: ResponsePayload::success("ok"),
375 id: Id::Number(1),
376 })
377 .unwrap();
378 let exp = r#"{"id":1,"result":"ok"}"#;
379 assert_eq!(ser, exp);
380 }
381
382 #[test]
383 fn deserialize_success_call() {
384 let exp =
385 Response { jsonrpc: Some(TwoPointZero), payload: ResponsePayload::success(99_u64), id: Id::Number(11) };
386 let dsr: Response<u64> = serde_json::from_str(r#"{"jsonrpc":"2.0", "result":99, "id":11}"#).unwrap();
387 assert_eq!(dsr.jsonrpc, exp.jsonrpc);
388 assert_eq!(dsr.payload, exp.payload);
389 assert_eq!(dsr.id, exp.id);
390 }
391
392 #[test]
393 fn deserialize_err_call() {
394 let exp = Response {
395 jsonrpc: Some(TwoPointZero),
396 payload: ResponsePayload::error(ErrorObjectOwned::owned(1, "lo", None::<()>)),
397 id: Id::Number(11),
398 };
399 let dsr: Response<()> =
400 serde_json::from_str(r#"{"jsonrpc":"2.0","error":{"code":1,"message":"lo"},"id":11}"#).unwrap();
401 assert_eq!(dsr.jsonrpc, exp.jsonrpc);
402 assert_eq!(dsr.payload, exp.payload);
403 assert_eq!(dsr.id, exp.id);
404 }
405
406 #[test]
407 fn deserialize_call_missing_version_field() {
408 let exp = Response { jsonrpc: None, payload: ResponsePayload::success(99_u64), id: Id::Number(11) };
409 let dsr: Response<u64> = serde_json::from_str(r#"{"jsonrpc":null, "result":99, "id":11}"#).unwrap();
410 assert_eq!(dsr.jsonrpc, exp.jsonrpc);
411 assert_eq!(dsr.payload, exp.payload);
412 assert_eq!(dsr.id, exp.id);
413 }
414
415 #[test]
416 fn deserialize_with_unknown_field() {
417 let exp = Response { jsonrpc: None, payload: ResponsePayload::success(99_u64), id: Id::Number(11) };
418 let dsr: Response<u64> =
419 serde_json::from_str(r#"{"jsonrpc":null, "result":99, "id":11, "unknown":11}"#).unwrap();
420 assert_eq!(dsr.jsonrpc, exp.jsonrpc);
421 assert_eq!(dsr.payload, exp.payload);
422 assert_eq!(dsr.id, exp.id);
423 }
424}