1use anyhow::{Context, Result};
4use serde_json::Value;
5use std::io::{BufRead, BufReader, Write};
6
7use super::handlers::{handle_method, handle_notification};
8use super::protocol::{JsonRpcRequest, JsonRpcResponse};
9
10pub fn run_server() -> Result<()> {
12 let stdin = std::io::stdin();
13 let mut stdout = std::io::stdout();
14 let reader = BufReader::new(stdin.lock());
15
16 for line in reader.lines() {
17 let line = line.context("Failed to read from stdin")?;
18
19 if line.trim().is_empty() {
20 continue;
21 }
22
23 let response = handle_request(&line);
24
25 if let Some(resp) = response {
26 let output = serde_json::to_string(&resp)?;
27 writeln!(stdout, "{}", output)?;
28 stdout.flush()?;
29 }
30 }
31
32 Ok(())
33}
34
35pub fn handle_request(line: &str) -> Option<JsonRpcResponse> {
56 let request: JsonRpcRequest = match serde_json::from_str(line) {
57 Ok(req) => req,
58 Err(e) => {
59 return Some(JsonRpcResponse::error(
60 Value::Null,
61 -32700,
62 &format!("Parse error: {}", e),
63 ));
64 }
65 };
66
67 if request.jsonrpc != "2.0" {
69 return Some(JsonRpcResponse::error(
70 request.id.unwrap_or(Value::Null),
71 -32600,
72 "Invalid JSON-RPC version",
73 ));
74 }
75
76 let id = match request.id {
78 Some(id) => id,
79 None => {
80 handle_notification(&request.method, request.params.as_ref());
82 return None;
83 }
84 };
85
86 let result = handle_method(&request.method, request.params.as_ref());
87
88 match result {
89 Ok(value) => Some(JsonRpcResponse::success(id, value)),
90 Err(e) => Some(JsonRpcResponse::error(id, -32603, &e.to_string())),
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_handle_request_parse_error() {
100 let response = handle_request("{invalid json}");
101 assert!(response.is_some());
102 let resp = response.unwrap();
103 assert!(resp.error.is_some());
104 assert_eq!(resp.error.as_ref().unwrap().code, -32700);
105 }
106
107 #[test]
108 fn test_handle_request_invalid_version() {
109 let response = handle_request(r#"{"jsonrpc":"1.0","method":"test","id":1}"#);
110 assert!(response.is_some());
111 let resp = response.unwrap();
112 assert!(resp.error.is_some());
113 assert_eq!(resp.error.as_ref().unwrap().code, -32600);
114 }
115
116 #[test]
117 fn test_handle_request_notification() {
118 let response = handle_request(r#"{"jsonrpc":"2.0","method":"notifications/initialized"}"#);
119 assert!(response.is_none());
120 }
121}