use crate::error::{Error, Result};
use crate::messages::{Event, Request, Response};
use serde::{Deserialize, Serialize};
pub struct Protocol;
impl Protocol {
pub fn serialize<T: Serialize>(message: &T) -> Result<String> {
let json = serde_json::to_string(message)?;
Ok(format!("{}\n", json))
}
pub fn deserialize<T: for<'de> Deserialize<'de>>(line: &str) -> Result<T> {
let trimmed = line.trim();
if trimmed.is_empty() {
return Err(Error::Protocol("Empty line".to_string()));
}
Ok(serde_json::from_str(trimmed)?)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "message_class", rename_all = "snake_case")]
pub enum MessageEnvelope {
Request(Request),
Response(Response),
Event(Event),
}
#[cfg(test)]
mod tests {
use super::*;
use crate::messages::*;
#[test]
fn test_serialize_deserialize() {
let request = Request {
message_type: "request".to_string(),
id: "test-123".to_string(),
session_id: Some("session-456".to_string()),
payload: RequestPayload::Initialize(InitializeRequest {
working_directory: Some("/home/user".to_string()),
environment: None,
capabilities: None,
}),
metadata: None,
};
let serialized = Protocol::serialize(&request).unwrap();
assert!(serialized.ends_with('\n'));
let deserialized: Request = Protocol::deserialize(&serialized).unwrap();
assert_eq!(deserialized.id, request.id);
}
#[test]
fn test_empty_line_error() {
let result: Result<Request> = Protocol::deserialize("");
assert!(result.is_err());
}
#[test]
fn test_invalid_json_error() {
let result: Result<Request> = Protocol::deserialize("not valid json");
assert!(result.is_err());
}
}