atomcode_core/lsp/
jsonrpc.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use tokio::io::{AsyncBufReadExt, AsyncReadExt, BufReader};
4
5#[derive(Debug, Serialize, Deserialize)]
6pub struct Request {
7 pub jsonrpc: String,
8 pub id: u64,
9 pub method: String,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 pub params: Option<Value>,
12}
13
14#[derive(Debug, Serialize, Deserialize)]
15pub struct Notification {
16 pub jsonrpc: String,
17 pub method: String,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub params: Option<Value>,
20}
21
22pub fn encode(body: &[u8]) -> Vec<u8> {
23 let header = format!("Content-Length: {}\r\n\r\n", body.len());
24 let mut msg = header.into_bytes();
25 msg.extend_from_slice(body);
26 msg
27}
28
29pub async fn read_message<R: tokio::io::AsyncRead + Unpin>(
30 reader: &mut BufReader<R>,
31) -> anyhow::Result<Value> {
32 let mut content_length: usize = 0;
33 let mut line = String::new();
34 loop {
35 line.clear();
36 let n = reader.read_line(&mut line).await?;
37 if n == 0 {
38 anyhow::bail!("EOF while reading LSP header");
39 }
40 let trimmed = line.trim();
41 if trimmed.is_empty() {
42 break;
43 }
44 if let Some(len_str) = trimmed.strip_prefix("Content-Length:") {
45 content_length = len_str.trim().parse()?;
46 }
47 }
48 if content_length == 0 {
49 anyhow::bail!("No Content-Length in LSP message");
50 }
51 let mut body = vec![0u8; content_length];
52 reader.read_exact(&mut body).await?;
53 Ok(serde_json::from_slice(&body)?)
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn encode_format() {
62 let body = b"{\"jsonrpc\":\"2.0\"}";
63 let encoded = encode(body);
64 let expected = format!("Content-Length: {}\r\n\r\n{}", body.len(), "{\"jsonrpc\":\"2.0\"}");
65 assert_eq!(encoded, expected.as_bytes());
66 }
67
68 #[tokio::test]
69 async fn read_message_parses() {
70 let body = b"{\"jsonrpc\":\"2.0\",\"id\":1}";
71 let raw = format!("Content-Length: {}\r\n\r\n{}", body.len(), std::str::from_utf8(body).unwrap());
72 let cursor = std::io::Cursor::new(raw.into_bytes());
73 let mut reader = BufReader::new(cursor);
74 let msg = read_message(&mut reader).await.unwrap();
75 assert_eq!(msg["jsonrpc"], "2.0");
76 assert_eq!(msg["id"], 1);
77 }
78
79 #[tokio::test]
80 async fn read_message_eof_error() {
81 let cursor = std::io::Cursor::new(Vec::<u8>::new());
82 let mut reader = BufReader::new(cursor);
83 let result = read_message(&mut reader).await;
84 assert!(result.is_err());
85 assert!(result.unwrap_err().to_string().contains("EOF"));
86 }
87}