use serde::{Deserialize, Deserializer, Serialize, de};
use serde_json::Value;
pub(crate) const METHOD_NOT_FOUND: i64 = -32601;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(untagged)]
pub(crate) enum RequestId {
Number(i64),
String(String),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) struct JsonRpcRequest {
pub(crate) jsonrpc: String,
pub(crate) id: RequestId,
pub(crate) method: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(crate) params: Option<Value>,
}
impl JsonRpcRequest {
pub(crate) fn new(id: RequestId, method: impl Into<String>, params: Option<Value>) -> Self {
Self {
jsonrpc: "2.0".to_string(),
id,
method: method.into(),
params,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) struct JsonRpcResponse {
pub(crate) jsonrpc: String,
pub(crate) id: RequestId,
pub(crate) result: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) struct JsonRpcError {
pub(crate) jsonrpc: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(crate) id: Option<RequestId>,
pub(crate) error: ErrorData,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) struct JsonRpcNotification {
pub(crate) jsonrpc: String,
pub(crate) method: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(crate) params: Option<Value>,
}
impl JsonRpcNotification {
pub(crate) fn new(method: impl Into<String>, params: Option<Value>) -> Self {
Self {
jsonrpc: "2.0".to_string(),
method: method.into(),
params,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) struct ErrorData {
pub(crate) code: i64,
pub(crate) message: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(crate) data: Option<Value>,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum JsonRpcMessage {
Response(JsonRpcResponse),
Error(JsonRpcError),
Notification(JsonRpcNotification),
Request(JsonRpcRequest),
}
impl<'de> Deserialize<'de> for JsonRpcMessage {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let value = Value::deserialize(deserializer)?;
if value.get("jsonrpc").and_then(Value::as_str) != Some("2.0") {
return Err(de::Error::custom(
"JSON-RPC message missing jsonrpc \"2.0\"",
));
}
#[derive(Deserialize)]
#[serde(untagged)]
enum UntaggedMessage {
Response(JsonRpcResponse),
Error(JsonRpcError),
Notification(JsonRpcNotification),
Request(JsonRpcRequest),
}
match UntaggedMessage::deserialize(value).map_err(de::Error::custom)? {
UntaggedMessage::Response(message) => Ok(JsonRpcMessage::Response(message)),
UntaggedMessage::Error(message) => Ok(JsonRpcMessage::Error(message)),
UntaggedMessage::Notification(message) => Ok(JsonRpcMessage::Notification(message)),
UntaggedMessage::Request(message) => Ok(JsonRpcMessage::Request(message)),
}
}
}