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;
#[derive(Clone, Debug, PartialEq)]
pub struct Response<R, E, EM=crate::error::StrBuf> {
pub jsonrpc: Version,
pub payload: Result<R, Error<E, EM>>,
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> {
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>()?);
},
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]
pub const fn result(jsonrpc: Version, result: R, id: Option<Id>) -> Self {
Self {
jsonrpc,
payload: Ok(result),
id,
}
}
#[inline]
pub const fn error(jsonrpc: Version, error: Error<E, EM>, id: Option<Id>) -> Self {
Self {
jsonrpc,
payload: Err(error),
id,
}
}
}