use std::fmt::{self, Debug, Formatter};
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use super::{Error, Id, Result, Version};
#[derive(Clone, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
enum Kind {
Ok { result: Value },
Err { error: Error },
}
#[derive(Clone, PartialEq, Deserialize, Serialize)]
pub struct Response {
jsonrpc: Version,
#[serde(flatten)]
kind: Kind,
id: Id,
}
impl Response {
pub const fn from_ok(id: Id, result: Value) -> Self {
Response {
jsonrpc: Version,
kind: Kind::Ok { result },
id,
}
}
pub const fn from_error(id: Id, error: Error) -> Self {
Response {
jsonrpc: Version,
kind: Kind::Err { error },
id,
}
}
pub fn from_parts(id: Id, body: Result<Value>) -> Self {
match body {
Ok(result) => Response::from_ok(id, result),
Err(error) => Response::from_error(id, error),
}
}
pub fn into_parts(self) -> (Id, Result<Value>) {
match self.kind {
Kind::Ok { result } => (self.id, Ok(result)),
Kind::Err { error } => (self.id, Err(error)),
}
}
pub const fn is_ok(&self) -> bool {
matches!(self.kind, Kind::Ok { .. })
}
pub const fn is_error(&self) -> bool {
!self.is_ok()
}
pub const fn result(&self) -> Option<&Value> {
match &self.kind {
Kind::Ok { result } => Some(result),
_ => None,
}
}
pub const fn error(&self) -> Option<&Error> {
match &self.kind {
Kind::Err { error } => Some(error),
_ => None,
}
}
pub const fn id(&self) -> &Id {
&self.id
}
}
impl Debug for Response {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let mut d = f.debug_struct("Response");
d.field("jsonrpc", &self.jsonrpc);
match &self.kind {
Kind::Ok { result } => d.field("result", result),
Kind::Err { error } => d.field("error", error),
};
d.field("id", &self.id).finish()
}
}
impl FromStr for Response {
type Err = serde_json::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
serde_json::from_str(s)
}
}