jsonrpc_base/
response.rs

1use super::{helpers, Error};
2use alloc::string::{String, ToString};
3use core::{fmt, str::FromStr};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7/// JSON-RPC response
8#[derive(Serialize, Deserialize, Debug, Clone)]
9pub struct Response {
10    /// Protocol header
11    pub jsonrpc: String,
12
13    /// Result variant representing success
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub result: Option<Value>,
16
17    /// Result variant representing error
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub error: Option<Error>,
20
21    /// ID of the request that originated the response
22    pub id: Value,
23}
24
25impl Response {
26    /// Create a new response representing a success
27    pub fn ok<I, V>(id: I, value: V) -> Self
28    where
29        I: Into<Value>,
30        V: Into<Value>,
31    {
32        Self {
33            jsonrpc: "2.0".to_string(),
34            result: Some(value.into()),
35            error: None,
36            id: id.into(),
37        }
38    }
39
40    /// Create a new response representing an error
41    pub fn err<I, E>(id: I, err: E) -> Self
42    where
43        I: Into<Value>,
44        E: Into<Error>,
45    {
46        Self {
47            jsonrpc: "2.0".to_string(),
48            result: None,
49            error: Some(err.into()),
50            id: id.into(),
51        }
52    }
53
54    /// Parse a message into the response
55    pub fn parse(s: &str) -> Result<(Self, &str), Error> {
56        let (message, remainder) = helpers::get_content_length(s)?;
57        let response = Response::parse_json(message)?;
58        Ok((response, remainder))
59    }
60
61    /// Parse a response from the provided JSON
62    pub fn parse_json(json: &str) -> Result<Self, Error> {
63        serde_json::from_str(json).map_err(|e| Error {
64            code: Error::INVALID_REQUEST,
65            message: e.to_string(),
66            data: Some(Value::String(json.to_string())),
67        })
68    }
69}
70
71impl<T, E> From<Response> for Result<T, E>
72where
73    T: From<Value>,
74    E: From<Error>,
75{
76    fn from(value: Response) -> Self {
77        match (value.result, value.error) {
78            (Some(result), _) => Ok(result.into()),
79            (_, Some(err)) => Err(err.into()),
80            (_, _) => Err(Error {
81                code: Error::INVALID_REQUEST,
82                message: "the provided respose header is invalid".to_string(),
83                data: None,
84            }
85            .into()),
86        }
87    }
88}
89
90impl fmt::Display for Response {
91    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92        serde_json::to_string(&self)
93            .map_err(|_| fmt::Error)
94            .and_then(|m| write!(f, "Content-Length: {}\r\n\r\n{}", m.len(), m))
95    }
96}
97
98impl FromStr for Response {
99    type Err = Error;
100
101    fn from_str(s: &str) -> Result<Self, Self::Err> {
102        Self::parse(s).map(|(json, _)| json)
103    }
104}
105
106#[cfg(feature = "std")]
107mod io {
108    use super::*;
109    use std::io::prelude::*;
110
111    impl Response {
112        /// Read a response from a reader.
113        ///
114        /// Returns the number of consumed bytes and the response.
115        pub fn try_from_reader<R>(reader: R) -> Result<(usize, Self), Error>
116        where
117            R: Read,
118        {
119            let (n, contents) = helpers::get_content_from_reader(reader)?;
120            let response = Response::parse_json(&contents)?;
121            Ok((n, response))
122        }
123
124        /// Write a response to a writer and return the number of bytes written.
125        pub fn try_to_writer<W>(&self, mut writer: W) -> Result<usize, Error>
126        where
127            W: Write,
128        {
129            writer
130                .write(self.to_string().as_bytes())
131                .map_err(|e| Error {
132                    code: Error::PARSE_ERROR,
133                    message: e.to_string(),
134                    data: serde_json::to_value(&self).ok(),
135                })
136        }
137    }
138}