tendermint_rpc/
response.rs

1//! JSON-RPC response types
2
3use std::io::Read;
4
5use serde::{de::DeserializeOwned, Deserialize, Serialize};
6
7use crate::{response_error::ResponseError, Error, Id, Version};
8
9/// JSON-RPC responses
10pub trait Response: DeserializeOwned + Sized {
11    /// Parse a JSON-RPC response from a JSON string
12    fn from_string(response: impl AsRef<[u8]>) -> Result<Self, Error> {
13        let wrapper: Wrapper<Self> =
14            serde_json::from_slice(response.as_ref()).map_err(Error::serde)?;
15        wrapper.into_result()
16    }
17
18    /// Parse a JSON-RPC response from an `io::Reader`
19    fn from_reader(reader: impl Read) -> Result<Self, Error> {
20        let wrapper: Wrapper<Self> = serde_json::from_reader(reader).map_err(Error::serde)?;
21        wrapper.into_result()
22    }
23}
24
25/// JSON-RPC response wrapper (i.e. message envelope)
26#[derive(Debug, Deserialize, Serialize, Clone)]
27pub struct Wrapper<R> {
28    /// JSON-RPC version
29    jsonrpc: Version,
30
31    /// Identifier included in request
32    id: Id,
33
34    /// Results of request (if successful)
35    result: Option<R>,
36
37    /// Error message if unsuccessful
38    error: Option<ResponseError>,
39}
40
41impl<R> Wrapper<R> {
42    /// Get JSON-RPC version
43    pub fn version(&self) -> &Version {
44        &self.jsonrpc
45    }
46
47    /// Get JSON-RPC ID
48    #[allow(dead_code)]
49    pub fn id(&self) -> &Id {
50        &self.id
51    }
52
53    /// Convert this wrapper into the underlying error, if any
54    pub fn into_error(self) -> Option<Error> {
55        self.error.map(Error::response)
56    }
57
58    /// Convert this wrapper into a result type
59    pub fn into_result(self) -> Result<R, Error> {
60        // Ensure we're using a supported RPC version
61        self.version().ensure_supported()?;
62
63        if let Some(e) = self.error {
64            Err(Error::response(e))
65        } else if let Some(result) = self.result {
66            Ok(result)
67        } else {
68            Err(Error::malformed_json())
69        }
70    }
71
72    pub fn new_with_id(id: Id, result: Option<R>, error: Option<ResponseError>) -> Self {
73        Self {
74            jsonrpc: Version::current(),
75            id,
76            result,
77            error,
78        }
79    }
80}