use crate::error::ResponseError;
use crate::types::Id;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
pub jsonrpc: String,
}
impl Default for Message {
fn default() -> Self {
Self {
jsonrpc: "2.0".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RequestMessage {
pub jsonrpc: String,
pub id: Id,
pub method: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub params: Option<serde_json::Value>,
}
impl RequestMessage {
pub fn new(id: impl Into<Id>, method: impl Into<String>) -> Self {
Self {
jsonrpc: "2.0".to_string(),
id: id.into(),
method: method.into(),
params: None,
}
}
pub fn with_params(
id: impl Into<Id>,
method: impl Into<String>,
params: serde_json::Value,
) -> Self {
Self {
jsonrpc: "2.0".to_string(),
id: id.into(),
method: method.into(),
params: Some(params),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResponseMessage {
pub jsonrpc: String,
pub id: Option<Id>,
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<ResponseError>,
}
impl ResponseMessage {
pub fn success(id: impl Into<Id>, result: serde_json::Value) -> Self {
Self {
jsonrpc: "2.0".to_string(),
id: Some(id.into()),
result: Some(result),
error: None,
}
}
pub fn error(id: Option<Id>, error: ResponseError) -> Self {
Self {
jsonrpc: "2.0".to_string(),
id,
result: None,
error: Some(error),
}
}
pub fn is_error(&self) -> bool {
self.error.is_some()
}
pub fn get_error(&self) -> Option<&ResponseError> {
self.error.as_ref()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NotificationMessage {
pub jsonrpc: String,
pub method: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub params: Option<serde_json::Value>,
}
impl NotificationMessage {
pub fn new(method: impl Into<String>) -> Self {
Self {
jsonrpc: "2.0".to_string(),
method: method.into(),
params: None,
}
}
pub fn with_params(method: impl Into<String>, params: serde_json::Value) -> Self {
Self {
jsonrpc: "2.0".to_string(),
method: method.into(),
params: Some(params),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RpcMessage {
Request(RequestMessage), Notification(NotificationMessage), Response(ResponseMessage), }
impl RpcMessage {
pub fn is_request(&self) -> bool {
matches!(self, RpcMessage::Request(_))
}
pub fn is_response(&self) -> bool {
matches!(self, RpcMessage::Response(_))
}
pub fn is_notification(&self) -> bool {
matches!(self, RpcMessage::Notification(_))
}
pub fn method(&self) -> Option<&str> {
match self {
RpcMessage::Request(req) => Some(&req.method),
RpcMessage::Notification(notif) => Some(¬if.method),
RpcMessage::Response(_) => None,
}
}
pub fn id(&self) -> Option<&Id> {
match self {
RpcMessage::Request(req) => Some(&req.id),
RpcMessage::Response(resp) => resp.id.as_ref(),
RpcMessage::Notification(_) => None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CancelParams {
pub id: Id,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgressParams<T> {
pub token: crate::types::ProgressToken,
pub value: T,
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_request_message_serialization() {
let request = RequestMessage::with_params(1, "test/method", json!({"key": "value"}));
let serialized = serde_json::to_string(&request).unwrap();
let deserialized: RequestMessage = serde_json::from_str(&serialized).unwrap();
assert_eq!(request.jsonrpc, "2.0");
assert_eq!(request.id, Id::Number(1));
assert_eq!(request.method, "test/method");
assert_eq!(deserialized.jsonrpc, request.jsonrpc);
}
#[test]
fn test_response_message_success() {
let response = ResponseMessage::success(1, json!({"result": "success"}));
assert!(!response.is_error());
assert!(response.result.is_some());
assert!(response.error.is_none());
}
#[test]
fn test_response_message_error() {
let error = ResponseError::new(-32600, "Invalid Request");
let response = ResponseMessage::error(Some(Id::Number(1)), error);
assert!(response.is_error());
assert!(response.result.is_none());
assert!(response.error.is_some());
}
#[test]
fn test_notification_message() {
let notification = NotificationMessage::with_params("test/notify", json!({"data": "test"}));
assert_eq!(notification.jsonrpc, "2.0");
assert_eq!(notification.method, "test/notify");
assert!(notification.params.is_some());
}
#[test]
fn test_rpc_message_enum() {
let request = RpcMessage::Request(RequestMessage::new(1, "test"));
assert!(request.is_request());
assert!(!request.is_response());
assert!(!request.is_notification());
assert_eq!(request.method(), Some("test"));
assert_eq!(request.id(), Some(&Id::Number(1)));
}
}