use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value;
use crate::{ErrorCodes, Notification, Request};
fn deserialize_some<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(Some)
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
enum Version {
#[serde(rename = "2.0")]
TwoPointZero,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Id {
Number(i64),
String(String),
Null,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Eq)]
pub struct RequestObject {
jsonrpc: Version,
#[serde(default, deserialize_with = "deserialize_some")]
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<Id>,
#[serde(default)]
method: String,
#[serde(default, deserialize_with = "deserialize_some")]
#[serde(skip_serializing_if = "Option::is_none")]
params: Option<Value>,
}
impl RequestObject {
pub fn from_request<R>(id: Id, params: R::Params) -> Self
where
R: Request,
{
let params = serde_json::to_value(params).expect("Invalid request params");
let params = match params {
Value::Null => None,
Value::Array(_) | Value::Object(_) => Some(params),
_ => panic!("Parameters must be an object or array, if not omitted."),
};
Self {
jsonrpc: Version::TwoPointZero,
id: Some(id),
params,
method: R::METHOD.into(),
}
}
pub fn from_notification<N>(params: N::Params) -> Self
where
N: Notification,
{
let params = serde_json::to_value(params).expect("Invalid request params");
let params = match params {
Value::Null => None,
Value::Array(_) | Value::Object(_) => Some(params),
_ => panic!("Parameters must be an object or array, if not omitted."),
};
Self {
jsonrpc: Version::TwoPointZero,
method: N::METHOD.to_string(),
params,
id: None,
}
}
#[must_use]
pub fn method(&self) -> &str {
self.method.as_ref()
}
#[must_use]
pub const fn id(&self) -> Option<&Id> {
self.id.as_ref()
}
#[must_use]
pub const fn params(&self) -> Option<&Value> {
self.params.as_ref()
}
#[must_use]
pub fn into_parts(self) -> (String, Option<Id>, Option<Value>) {
(self.method, self.id, self.params)
}
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
enum Kind {
Ok { result: Value },
Err { error: Error },
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct Error {
pub code: ErrorCodes,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct ResponseObject {
jsonrpc: Version,
#[serde(flatten)]
kind: Kind,
id: Id,
}
impl ResponseObject {
pub fn from_success<R>(id: Id, result: R::Result) -> Self
where
R: Request,
{
let result = serde_json::to_value(result).unwrap();
Self {
jsonrpc: Version::TwoPointZero,
kind: Kind::Ok { result },
id,
}
}
#[must_use]
pub const fn from_error(id: Id, error: Error) -> Self {
Self {
jsonrpc: Version::TwoPointZero,
kind: Kind::Err { error },
id,
}
}
#[must_use]
pub const fn is_ok(&self) -> bool {
matches!(self.kind, Kind::Ok { .. })
}
#[must_use]
pub const fn is_error(&self) -> bool {
!self.is_ok()
}
#[must_use]
pub const fn id(&self) -> &Id {
&self.id
}
#[must_use]
pub const fn result(&self) -> Option<&Value> {
match &self.kind {
Kind::Ok { result } => Some(result),
Kind::Err { .. } => None,
}
}
#[must_use]
pub const fn error(&self) -> Option<&Error> {
match &self.kind {
Kind::Err { error } => Some(error),
Kind::Ok { .. } => None,
}
}
}