use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Deserialize)]
pub struct Request {
#[serde(default)]
pub id: Option<Value>,
pub method: String,
#[serde(default)]
pub params: Value,
}
impl Request {
pub fn is_notification(&self) -> bool {
self.id.is_none()
}
}
#[derive(Debug, Serialize)]
pub struct Response {
pub jsonrpc: &'static str,
pub id: Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<RpcError>,
}
#[derive(Debug, Serialize)]
pub struct RpcError {
pub code: i64,
pub message: String,
}
impl Response {
pub fn ok(id: Value, result: Value) -> Self {
Response {
jsonrpc: "2.0",
id,
result: Some(result),
error: None,
}
}
pub fn err(id: Value, code: i64, message: &str) -> Self {
Response {
jsonrpc: "2.0",
id,
result: None,
error: Some(RpcError {
code,
message: message.into(),
}),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn parses_request_with_id() {
let r: Request = serde_json::from_value(json!({
"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}
}))
.unwrap();
assert_eq!(r.method, "tools/list");
assert!(!r.is_notification());
}
#[test]
fn parses_notification_without_id() {
let r: Request = serde_json::from_value(json!({
"jsonrpc":"2.0","method":"notifications/initialized"
}))
.unwrap();
assert!(r.is_notification());
}
#[test]
fn ok_response_omits_error() {
let v = serde_json::to_value(Response::ok(json!(1), json!({"ok":true}))).unwrap();
assert_eq!(v, json!({"jsonrpc":"2.0","id":1,"result":{"ok":true}}));
}
#[test]
fn err_response_omits_result() {
let v = serde_json::to_value(Response::err(json!(2), -32601, "method not found")).unwrap();
assert_eq!(
v,
json!({"jsonrpc":"2.0","id":2,"error":{"code":-32601,"message":"method not found"}})
);
}
}