eth_jsonrpc_lib/rpc_response/
response.rs

1// Copyright Rivtower Technologies LLC.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::vec::Vec;
16
17use serde::de::Error as SError;
18use serde::{Deserialize, Deserializer, Serialize, Serializer};
19use serde_json::{from_value, Value};
20
21use crate::error::Error;
22use crate::rpc_request::{RequestInfo, ResponseResult};
23use crate::rpc_types::{Id, Version};
24
25#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
26pub struct RpcFailure {
27    pub jsonrpc: Option<Version>,
28    pub id: Id,
29    pub error: Error,
30}
31
32#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
33pub struct RpcSuccess {
34    pub jsonrpc: Option<Version>,
35    pub id: Id,
36    pub result: ResponseResult,
37}
38
39impl RpcSuccess {
40    pub fn new(info: RequestInfo) -> Self {
41        RpcSuccess {
42            jsonrpc: info.jsonrpc,
43            id: info.id,
44            result: ResponseResult::default(),
45        }
46    }
47
48    pub fn set_result(mut self, reuslt: ResponseResult) -> Self {
49        self.result = reuslt;
50        self
51    }
52
53    pub fn output(self) -> Output {
54        Output::Success(Box::new(self))
55    }
56}
57
58#[derive(Debug, PartialEq, Clone)]
59pub enum Output {
60    /// Success
61    Success(Box<RpcSuccess>),
62    /// Failure
63    Failure(RpcFailure),
64}
65
66impl Output {
67    /// Creates new failure output indicating malformed request.
68    pub fn invalid_request(info: RequestInfo) -> Self {
69        Output::Failure(RpcFailure::from_options(info, Error::invalid_request()))
70    }
71
72    /// Creates a system error
73    pub fn system_error(code: i64) -> Self {
74        Output::Failure(RpcFailure::from(Error::server_error(code, "system error")))
75    }
76}
77
78impl<'a> Deserialize<'a> for Output {
79    fn deserialize<D>(deserializer: D) -> Result<Output, D::Error>
80    where
81        D: Deserializer<'a>,
82    {
83        let v: Value = Deserialize::deserialize(deserializer)?;
84        from_value(v.clone())
85            .map(Output::Failure)
86            .or_else(|_| from_value(v).map(Output::Success))
87            .map_err(|_| D::Error::custom("")) // types must match
88    }
89}
90
91impl Serialize for Output {
92    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
93    where
94        S: Serializer,
95    {
96        match *self {
97            Output::Success(ref s) => s.serialize(serializer),
98            Output::Failure(ref f) => f.serialize(serializer),
99        }
100    }
101}
102
103impl From<Error> for RpcFailure {
104    fn from(err: Error) -> Self {
105        RpcFailure::from_options(RequestInfo::null(), err)
106    }
107}
108
109impl RpcFailure {
110    pub fn from_options(info: RequestInfo, err: Error) -> Self {
111        RpcFailure {
112            jsonrpc: info.jsonrpc,
113            id: info.id,
114            error: err,
115        }
116    }
117}
118
119#[derive(Debug, PartialEq)]
120pub enum RpcResponse {
121    /// Single response
122    Single(Box<Output>),
123    /// Response to batch request (batch of responses)
124    Batch(Vec<Output>),
125}
126
127impl<'a> Deserialize<'a> for RpcResponse {
128    fn deserialize<D>(deserializer: D) -> Result<RpcResponse, D::Error>
129    where
130        D: Deserializer<'a>,
131    {
132        let v: Value = Deserialize::deserialize(deserializer)?;
133        from_value(v.clone())
134            .map(RpcResponse::Batch)
135            .or_else(|_| from_value(v).map(RpcResponse::Single))
136            .map_err(|_| D::Error::custom("")) // types must match
137    }
138}
139
140impl Serialize for RpcResponse {
141    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
142    where
143        S: Serializer,
144    {
145        match *self {
146            RpcResponse::Single(ref o) => o.serialize(serializer),
147            RpcResponse::Batch(ref b) => b.serialize(serializer),
148        }
149    }
150}
151
152#[cfg(test)]
153mod tests {
154    use super::RpcSuccess;
155    use crate::rpc_request::{RequestInfo, ResponseResult};
156    use crate::rpc_types::{Id, Version};
157    use serde_json;
158
159    #[test]
160    fn test_rpc_deserialize() {
161        let rpc = RpcSuccess::new(RequestInfo::new(Some(Version::V2), Id::Num(2)))
162            .set_result(ResponseResult::Null);
163
164        let rpc_body = serde_json::to_string(&rpc).unwrap();
165        assert_eq!(rpc_body, r#"{"jsonrpc":"2.0","id":2,"result":null}"#);
166    }
167
168    #[test]
169    fn test_rpc_deserialize2() {
170        let rpc = RpcSuccess::new(RequestInfo::new(
171            Some(Version::V2),
172            Id::Str("2".to_string()),
173        ))
174        .set_result(ResponseResult::eth_blockNumber(3u64.into()));
175
176        let rpc_body = serde_json::to_string(&rpc).unwrap();
177        assert_eq!(rpc_body, r#"{"jsonrpc":"2.0","id":"2","result":"0x3"}"#);
178    }
179}