use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Serialize)]
pub struct JsonRpcRequest {
pub jsonrpc: &'static str,
pub id: u64,
pub method: String,
pub params: Value,
}
impl JsonRpcRequest {
pub fn new(id: u64, method: &str, params: Value) -> Self {
Self {
jsonrpc: "2.0",
id,
method: method.to_string(),
params,
}
}
}
#[derive(Debug, Serialize)]
pub struct JsonRpcNotification {
pub jsonrpc: &'static str,
pub method: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub params: Option<Value>,
}
impl JsonRpcNotification {
pub fn new(method: &str) -> Self {
Self {
jsonrpc: "2.0",
method: method.to_string(),
params: None,
}
}
pub fn with_params(method: &str, params: Value) -> Self {
Self {
jsonrpc: "2.0",
method: method.to_string(),
params: Some(params),
}
}
}
#[derive(Debug, Deserialize)]
pub struct JsonRpcResponse {
pub jsonrpc: String,
#[serde(default)]
pub id: Option<u64>,
#[serde(default)]
pub result: Option<Value>,
#[serde(default)]
pub error: Option<JsonRpcError>,
}
impl JsonRpcResponse {
pub fn is_success(&self) -> bool {
self.result.is_some() && self.error.is_none()
}
}
#[derive(Debug, Deserialize)]
pub struct JsonRpcError {
pub code: i32,
pub message: String,
#[serde(default)]
pub data: Option<Value>,
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_request_new() {
let request = JsonRpcRequest::new(1, "test", json!({}));
assert_eq!(request.jsonrpc, "2.0");
assert_eq!(request.id, 1);
assert_eq!(request.method, "test");
}
#[test]
fn test_response_is_success() {
let json_str = r#"{"jsonrpc": "2.0", "id": 1, "result": {}}"#;
let response: JsonRpcResponse = serde_json::from_str(json_str).unwrap();
assert!(response.is_success());
}
#[test]
fn test_response_is_not_success_on_error() {
let json_str = r#"{"jsonrpc": "2.0", "id": 1, "error": {"code": -1, "message": "fail"}}"#;
let response: JsonRpcResponse = serde_json::from_str(json_str).unwrap();
assert!(!response.is_success());
}
#[test]
fn test_notification_new() {
let notification = JsonRpcNotification::new("notifications/initialized");
assert_eq!(notification.jsonrpc, "2.0");
assert_eq!(notification.method, "notifications/initialized");
assert!(notification.params.is_none());
}
#[test]
fn test_notification_with_params() {
let notification =
JsonRpcNotification::with_params("notifications/test", json!({"key": "value"}));
assert_eq!(notification.jsonrpc, "2.0");
assert_eq!(notification.method, "notifications/test");
assert!(notification.params.is_some());
}
#[test]
fn test_notification_serializes_without_params() {
let notification = JsonRpcNotification::new("notifications/initialized");
let json = serde_json::to_string(¬ification).unwrap();
assert!(!json.contains("params"));
assert!(json.contains("notifications/initialized"));
}
}