json_rpc_types/
response.rs

1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2
3use crate::error::Error;
4use crate::version::Version;
5use crate::id::Id;
6use crate::utils::Key;
7
8use core::mem;
9
10///Response representation.
11///
12///When omitting `id`, it shall be serialized as `null` and means you're unable to identify `id` of
13///`Request`.
14///Note that JSON-RPCv2 specifies that `id` must be always present, therefore you're encouraged to
15///treat missing `id` as error, unless response is error itself, in which case it might be
16///indication that server treats request as invalid (e.g. unable to parse request's id).
17///
18///`jsonrpc` may be omitted during deserialization and defaults to v2.
19///
20///Type parameters:
21///
22///- `R`  - Type of payload for successful response
23///- `E`  - Type of optional data for `Error`.
24///- `EM` - Type of `E::M`, which is used for `message` field of error.
25#[derive(Clone, Debug, PartialEq)]
26pub struct Response<R, E, EM=crate::error::StrBuf> {
27    ///A String specifying the version of the JSON-RPC protocol.
28    pub jsonrpc: Version,
29
30    ///Content of response, depending on whether it is success or failure.
31    pub payload: Result<R, Error<E, EM>>,
32
33    ///An identifier established by the Client.
34    ///
35    ///If not present, it is sent in response to invalid request (e.g. unable to recognize id).
36    ///
37    ///Must be present always, so `None` is serialized as `null`
38    pub id: Option<Id>,
39}
40
41impl<R: Serialize, E: Serialize, EM: Serialize> Serialize for Response<R, E, EM> {
42    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
43        use serde::ser::SerializeMap;
44
45        let mut state = ser.serialize_map(Some(3))?;
46
47        state.serialize_entry("jsonrpc", &self.jsonrpc)?;
48        match self.payload {
49            Ok(ref result) => state.serialize_entry("result", result),
50            Err(ref error) => state.serialize_entry("error", error),
51        }?;
52        match self.id {
53            Some(ref id) => state.serialize_entry("id", id),
54            None => state.serialize_entry("id", &()),
55        }?;
56
57        state.end()
58    }
59}
60
61impl<'de, R: Deserialize<'de>, E: Deserialize<'de>, EM: Deserialize<'de>> Deserialize<'de> for Response<R, E, EM> {
62    fn deserialize<D: Deserializer<'de>>(der: D) -> Result<Self, D::Error> {
63        use core::marker::PhantomData;
64        use serde::de::{self, Visitor};
65
66        struct MapVisit<R, E, EM>(PhantomData<(R, E, EM)>);
67
68        impl<'de, R: Deserialize<'de>, E: Deserialize<'de>, EM: Deserialize<'de>> Visitor<'de> for MapVisit<R, E, EM> {
69            type Value = Response<R, E, EM>;
70
71            #[inline]
72            fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
73                formatter.write_str("Object resembling JSON-RPC response type")
74            }
75
76            fn visit_map<A: de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
77                //Normally you'd use unitialized struct, but it is highly unlikely to guarantee
78                //safety of field-by-field initialization
79                let mut version = None;
80                let mut result = None;
81                let mut id = None;
82
83                while let Some(key) = map.next_key::<Key>()? {
84                    match key {
85                        Key::JsonRpc => {
86                            version = Some(map.next_value::<Version>()?);
87                        },
88                        //If for some reason user wishes to convey success with NULL, we need to respect that.
89                        //This cannot be the case for error as its format is well defined
90                        //And while spec does say `result` field MUST be object, theoretically NULL should qualify too.
91                        //This is hack because bitch cannot have specialization stabilized forever
92                        Key::Result if mem::size_of::<R>() == 0 => {
93                            if result.is_none() {
94                                result = Some(Ok(map.next_value::<R>()?));
95                            } else {
96                                return Err(serde::de::Error::custom("JSON-RPC Response contains both result and error field"));
97                            }
98                        }
99                        Key::Result => match map.next_value::<Option<R>>()? {
100                            Some(value) => if result.is_none() {
101                                result = Some(Ok(value));
102                            } else {
103                                return Err(serde::de::Error::custom("JSON-RPC Response contains both result and error field"));
104                            }
105                            None => continue,
106                        },
107                        Key::Error => match map.next_value::<Option<Error<E, EM>>>()? {
108                            Some(error) => if result.is_none() {
109                                result = Some(Err(error));
110                            } else {
111                                return Err(serde::de::Error::custom("JSON-RPC Response contains both error and result field"));
112                            }
113                            None => continue,
114                        },
115                        Key::Id => {
116                            id = map.next_value::<Option<Id>>()?;
117                        },
118                    }
119                }
120
121                Ok(Self::Value {
122                    jsonrpc: match version {
123                        Some(version) => version,
124                        None => Version::V2,
125                    },
126                    payload: match result {
127                        Some(payload) => payload,
128                        None => {
129                            return Err(serde::de::Error::custom("JSON-RPC Response is missing either result or error field."));
130                        }
131                    },
132                    id,
133                })
134            }
135        }
136
137        der.deserialize_map(MapVisit(PhantomData))
138    }
139}
140
141impl<R, E, EM> Response<R, E, EM> {
142    #[inline]
143    ///Creates successful response.
144    pub const fn result(jsonrpc: Version, result: R, id: Option<Id>) -> Self {
145        Self {
146            jsonrpc,
147            payload: Ok(result),
148            id,
149        }
150    }
151
152    #[inline]
153    ///Creates error response.
154    pub const fn error(jsonrpc: Version, error: Error<E, EM>, id: Option<Id>) -> Self {
155        Self {
156            jsonrpc,
157            payload: Err(error),
158            id,
159        }
160    }
161}