use crate::{
Error as RpcError, RequestWrapper, ResponseWrapper, RpcRequest, RpcResponse, JSONRPC_FIELD,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Value;
pub type MessageId = String;
#[derive(Debug, Clone, PartialEq)]
pub enum Message<Rq, Rs> {
Req { id: MessageId, req: Rq },
Res { id: MessageId, res: Rs },
Err { id: MessageId, err: RpcError },
}
impl<'de, Rq, Rs> Deserialize<'de> for Message<Rq, Rs>
where
Rq: RequestWrapper,
Rs: ResponseWrapper,
{
fn deserialize<D>(d: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let json = <Value as Deserialize>::deserialize(d)?;
if let Ok(req) = serde_json::from_value::<Request>(json.clone()) {
let id = req.id.clone();
let req = Rq::try_from_req(req).map_err(|err| {
serde::de::Error::custom(format!(
"Err converting from deserialized Request to wrapper: {err:#?}",
))
})?;
return Ok(Self::Req { id, req });
}
if let Ok(res) = serde_json::from_value::<IdentifiedResponse>(json) {
let id = res.res.id.clone();
match Rs::try_from_res(res).map_err(|err| {
serde::de::Error::custom(format!(
"Err converting from deserialized Response to wrapper: {err:#?}",
))
})? {
Ok(res) => return Ok(Self::Res { id, res }),
Err(err) => return Ok(Self::Err { id, err }),
}
}
Err(serde::de::Error::custom(
"Failed to deserialize any Message variant",
))
}
}
impl<Rq, Rs> Serialize for Message<Rq, Rs>
where
Rq: RequestWrapper,
Rs: ResponseWrapper,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Self::Req { id, req } => {
let req: Request = req.into_req(id);
req.serialize(serializer)
}
Self::Res { id, res } => {
let res: IdentifiedResponse = res.into_res(id);
res.serialize(serializer)
}
Self::Err { id, err } => {
let err_res = Response::from_error(id, err.clone());
err_res.serialize(serializer)
}
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct Request {
pub jsonrpc: String,
pub method: String,
pub params: serde_json::Value,
pub id: String,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct IdentifiedResponse {
pub id: String,
pub res: Response,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct Response {
pub jsonrpc: String,
pub result: Option<serde_json::Value>,
pub error: Option<crate::error::Error>,
pub id: String,
}
impl Request {
pub fn from_req(id: impl ToString, req: impl RpcRequest) -> Self {
req.into_request(id).unwrap()
}
}
impl Response {
pub fn from_error(id: impl ToString, error: crate::error::Error) -> Self {
Self {
jsonrpc: JSONRPC_FIELD.to_string(),
result: None,
error: Some(error),
id: id.to_string(),
}
}
pub fn from_res(id: impl ToString, res: impl RpcResponse) -> Self {
res.into_response(id).unwrap().res
}
}