1use crate::types::{LspError, LspResult};
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10use std::collections::HashMap;
11use std::io::{self, BufRead, BufReader, Write};
12use tokio::io::{AsyncBufReadExt, AsyncWriteExt};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct JsonRpcRequest {
17 pub jsonrpc: String,
19 pub id: serde_json::Value,
21 pub method: String,
23 #[serde(skip_serializing_if = "Option::is_none")]
25 pub params: Option<Value>,
26}
27
28impl JsonRpcRequest {
29 pub fn new(id: serde_json::Value, method: String, params: Option<Value>) -> Self {
31 Self {
32 jsonrpc: "2.0".to_string(),
33 id,
34 method,
35 params,
36 }
37 }
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct JsonRpcResponse {
43 pub jsonrpc: String,
45 pub id: serde_json::Value,
47 #[serde(skip_serializing_if = "Option::is_none")]
49 pub result: Option<Value>,
50 #[serde(skip_serializing_if = "Option::is_none")]
52 pub error: Option<JsonRpcError>,
53}
54
55impl JsonRpcResponse {
56 pub fn success(id: serde_json::Value, result: Value) -> Self {
58 Self {
59 jsonrpc: "2.0".to_string(),
60 id,
61 result: Some(result),
62 error: None,
63 }
64 }
65
66 pub fn error(id: serde_json::Value, error: JsonRpcError) -> Self {
68 Self {
69 jsonrpc: "2.0".to_string(),
70 id,
71 result: None,
72 error: Some(error),
73 }
74 }
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct JsonRpcError {
80 pub code: i32,
82 pub message: String,
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub data: Option<Value>,
87}
88
89impl JsonRpcError {
90 pub fn new(code: i32, message: String) -> Self {
92 Self {
93 code,
94 message,
95 data: None,
96 }
97 }
98
99 pub fn parse_error(message: String) -> Self {
101 Self::new(-32700, message)
102 }
103
104 pub fn invalid_request(message: String) -> Self {
106 Self::new(-32600, message)
107 }
108
109 pub fn method_not_found(method: String) -> Self {
111 Self::new(-32601, format!("Method not found: {}", method))
112 }
113
114 pub fn invalid_params(message: String) -> Self {
116 Self::new(-32602, message)
117 }
118
119 pub fn internal_error(message: String) -> Self {
121 Self::new(-32603, message)
122 }
123
124 pub fn server_error(code: i32, message: String) -> Self {
126 Self::new(code, message)
127 }
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct JsonRpcNotification {
133 pub jsonrpc: String,
135 pub method: String,
137 #[serde(skip_serializing_if = "Option::is_none")]
139 pub params: Option<Value>,
140}
141
142impl JsonRpcNotification {
143 pub fn new(method: String, params: Option<Value>) -> Self {
145 Self {
146 jsonrpc: "2.0".to_string(),
147 method,
148 params,
149 }
150 }
151}
152
153#[derive(Debug, Clone)]
155pub enum LspMessage {
156 Request(JsonRpcRequest),
158 Response(JsonRpcResponse),
160 Notification(JsonRpcNotification),
162}
163
164impl LspMessage {
165 pub fn from_json(json: &str) -> LspResult<Self> {
167 let value: Value = serde_json::from_str(json)
168 .map_err(|e| LspError::ParseError(format!("Failed to parse JSON: {}", e)))?;
169
170 if value.get("result").is_some() || value.get("error").is_some() {
172 let response: JsonRpcResponse = serde_json::from_value(value)
173 .map_err(|e| LspError::ParseError(format!("Failed to parse response: {}", e)))?;
174 Ok(LspMessage::Response(response))
175 }
176 else if value.get("id").is_some() && value.get("method").is_some() {
178 let request: JsonRpcRequest = serde_json::from_value(value)
179 .map_err(|e| LspError::ParseError(format!("Failed to parse request: {}", e)))?;
180 Ok(LspMessage::Request(request))
181 }
182 else if value.get("method").is_some() {
184 let notification: JsonRpcNotification = serde_json::from_value(value).map_err(|e| {
185 LspError::ParseError(format!("Failed to parse notification: {}", e))
186 })?;
187 Ok(LspMessage::Notification(notification))
188 } else {
189 Err(LspError::InvalidRequest(
190 "Message must be a request, response, or notification".to_string(),
191 ))
192 }
193 }
194
195 pub fn to_json(&self) -> LspResult<String> {
197 match self {
198 LspMessage::Request(req) => serde_json::to_string(req).map_err(|e| {
199 LspError::SerializationError(format!("Failed to serialize request: {}", e))
200 }),
201 LspMessage::Response(resp) => serde_json::to_string(resp).map_err(|e| {
202 LspError::SerializationError(format!("Failed to serialize response: {}", e))
203 }),
204 LspMessage::Notification(notif) => serde_json::to_string(notif).map_err(|e| {
205 LspError::SerializationError(format!("Failed to serialize notification: {}", e))
206 }),
207 }
208 }
209}
210
211pub struct StdioTransport {
213 reader: BufReader<io::Stdin>,
214 writer: io::Stdout,
215}
216
217impl StdioTransport {
218 pub fn new() -> Self {
220 Self {
221 reader: BufReader::new(io::stdin()),
222 writer: io::stdout(),
223 }
224 }
225
226 pub fn read_message(&mut self) -> LspResult<LspMessage> {
228 let mut headers = HashMap::new();
229
230 loop {
232 let mut line = String::new();
233 self.reader
234 .read_line(&mut line)
235 .map_err(|e| LspError::IoError(format!("Failed to read header: {}", e)))?;
236
237 if line == "\r\n" || line == "\n" {
238 break;
239 }
240
241 let line = line.trim();
242 if line.is_empty() {
243 break;
244 }
245
246 if let Some((key, value)) = line.split_once(':') {
247 headers.insert(key.trim().to_string(), value.trim().to_string());
248 }
249 }
250
251 let content_length: usize = headers
253 .get("Content-Length")
254 .ok_or_else(|| LspError::InvalidRequest("Missing Content-Length header".to_string()))?
255 .parse()
256 .map_err(|e| LspError::InvalidRequest(format!("Invalid Content-Length: {}", e)))?;
257
258 let mut content = vec![0u8; content_length];
260 use std::io::Read;
261 self.reader
262 .read_exact(&mut content)
263 .map_err(|e| LspError::IoError(format!("Failed to read content: {}", e)))?;
264
265 let json = String::from_utf8(content)
266 .map_err(|e| LspError::ParseError(format!("Invalid UTF-8: {}", e)))?;
267
268 LspMessage::from_json(&json)
269 }
270
271 pub fn write_message(&mut self, message: &LspMessage) -> LspResult<()> {
273 let json = message.to_json()?;
274 let content_length = json.len();
275
276 write!(
277 self.writer,
278 "Content-Length: {}\r\n\r\n{}",
279 content_length, json
280 )
281 .map_err(|e| LspError::IoError(format!("Failed to write message: {}", e)))?;
282
283 self.writer
284 .flush()
285 .map_err(|e| LspError::IoError(format!("Failed to flush output: {}", e)))?;
286
287 Ok(())
288 }
289}
290
291impl Default for StdioTransport {
292 fn default() -> Self {
293 Self::new()
294 }
295}
296
297pub struct AsyncStdioTransport {
299 reader: tokio::io::BufReader<tokio::io::Stdin>,
300 writer: tokio::io::Stdout,
301}
302
303impl AsyncStdioTransport {
304 pub fn new() -> Self {
306 Self {
307 reader: tokio::io::BufReader::new(tokio::io::stdin()),
308 writer: tokio::io::stdout(),
309 }
310 }
311
312 pub async fn read_message(&mut self) -> LspResult<LspMessage> {
314 let mut headers = HashMap::new();
315
316 loop {
318 let mut line = String::new();
319 self.reader
320 .read_line(&mut line)
321 .await
322 .map_err(|e| LspError::IoError(format!("Failed to read header: {}", e)))?;
323
324 if line == "\r\n" || line == "\n" {
325 break;
326 }
327
328 let line = line.trim();
329 if line.is_empty() {
330 break;
331 }
332
333 if let Some((key, value)) = line.split_once(':') {
334 headers.insert(key.trim().to_string(), value.trim().to_string());
335 }
336 }
337
338 let content_length: usize = headers
340 .get("Content-Length")
341 .ok_or_else(|| LspError::InvalidRequest("Missing Content-Length header".to_string()))?
342 .parse()
343 .map_err(|e| LspError::InvalidRequest(format!("Invalid Content-Length: {}", e)))?;
344
345 let mut content = vec![0u8; content_length];
347 use tokio::io::AsyncReadExt;
348 self.reader
349 .read_exact(&mut content)
350 .await
351 .map_err(|e| LspError::IoError(format!("Failed to read content: {}", e)))?;
352
353 let json = String::from_utf8(content)
354 .map_err(|e| LspError::ParseError(format!("Invalid UTF-8: {}", e)))?;
355
356 LspMessage::from_json(&json)
357 }
358
359 pub async fn write_message(&mut self, message: &LspMessage) -> LspResult<()> {
361 let json = message.to_json()?;
362 let content_length = json.len();
363
364 self.writer
365 .write_all(format!("Content-Length: {}\r\n\r\n{}", content_length, json).as_bytes())
366 .await
367 .map_err(|e| LspError::IoError(format!("Failed to write message: {}", e)))?;
368
369 self.writer
370 .flush()
371 .await
372 .map_err(|e| LspError::IoError(format!("Failed to flush output: {}", e)))?;
373
374 Ok(())
375 }
376}
377
378impl Default for AsyncStdioTransport {
379 fn default() -> Self {
380 Self::new()
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::*;
387 use serde_json::json;
388
389 #[test]
390 fn test_jsonrpc_request_creation() {
391 let req = JsonRpcRequest::new(
392 json!(1),
393 "initialize".to_string(),
394 Some(json!({"processId": 1234})),
395 );
396 assert_eq!(req.jsonrpc, "2.0");
397 assert_eq!(req.method, "initialize");
398 }
399
400 #[test]
401 fn test_jsonrpc_response_success() {
402 let resp = JsonRpcResponse::success(json!(1), json!({"capabilities": {}}));
403 assert_eq!(resp.jsonrpc, "2.0");
404 assert!(resp.result.is_some());
405 assert!(resp.error.is_none());
406 }
407
408 #[test]
409 fn test_jsonrpc_response_error() {
410 let error = JsonRpcError::parse_error("Invalid JSON".to_string());
411 let resp = JsonRpcResponse::error(json!(1), error);
412 assert!(resp.error.is_some());
413 assert!(resp.result.is_none());
414 }
415
416 #[test]
417 fn test_jsonrpc_notification_creation() {
418 let notif = JsonRpcNotification::new("initialized".to_string(), None);
419 assert_eq!(notif.jsonrpc, "2.0");
420 assert_eq!(notif.method, "initialized");
421 }
422
423 #[test]
424 fn test_lsp_message_from_request_json() {
425 let json_str =
426 r#"{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":1234}}"#;
427 let msg = LspMessage::from_json(json_str).unwrap();
428 match msg {
429 LspMessage::Request(req) => {
430 assert_eq!(req.method, "initialize");
431 }
432 _ => panic!("Expected request"),
433 }
434 }
435
436 #[test]
437 fn test_lsp_message_from_notification_json() {
438 let json_str = r#"{"jsonrpc":"2.0","method":"initialized"}"#;
439 let msg = LspMessage::from_json(json_str).unwrap();
440 match msg {
441 LspMessage::Notification(notif) => {
442 assert_eq!(notif.method, "initialized");
443 }
444 _ => panic!("Expected notification"),
445 }
446 }
447
448 #[test]
449 fn test_lsp_message_to_json() {
450 let req = JsonRpcRequest::new(json!(1), "initialize".to_string(), None);
451 let msg = LspMessage::Request(req);
452 let json_str = msg.to_json().unwrap();
453 assert!(json_str.contains("initialize"));
454 }
455
456 #[test]
457 fn test_jsonrpc_error_codes() {
458 let parse_err = JsonRpcError::parse_error("test".to_string());
459 assert_eq!(parse_err.code, -32700);
460
461 let invalid_req = JsonRpcError::invalid_request("test".to_string());
462 assert_eq!(invalid_req.code, -32600);
463
464 let method_not_found = JsonRpcError::method_not_found("test".to_string());
465 assert_eq!(method_not_found.code, -32601);
466
467 let invalid_params = JsonRpcError::invalid_params("test".to_string());
468 assert_eq!(invalid_params.code, -32602);
469
470 let internal_err = JsonRpcError::internal_error("test".to_string());
471 assert_eq!(internal_err.code, -32603);
472 }
473}