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