-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsplitls.rs
More file actions
87 lines (76 loc) · 2.63 KB
/
Copy pathsplitls.rs
File metadata and controls
87 lines (76 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use std::io::{self, BufRead, Write};
use serde_json::Value;
use splitscript::tooling::lsp::LanguageServer;
fn main() -> io::Result<()> {
let stdin = io::stdin();
let stdout = io::stdout();
let mut reader = stdin.lock();
let mut writer = stdout.lock();
let mut server = LanguageServer::default();
while let Some(message) = read_message(&mut reader)? {
for outgoing in server.handle(message) {
write_message(&mut writer, &outgoing)?;
}
writer.flush()?;
if server.should_exit() {
break;
}
}
Ok(())
}
fn read_message(reader: &mut impl BufRead) -> io::Result<Option<Value>> {
let mut content_length = None;
let mut saw_header = false;
loop {
let mut line = String::new();
let bytes = reader.read_line(&mut line)?;
if bytes == 0 {
return if saw_header {
Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"LSP message ended inside its headers",
))
} else {
Ok(None)
};
}
saw_header = true;
if line == "\r\n" || line == "\n" {
break;
}
if let Some((name, value)) = line.split_once(':')
&& name.eq_ignore_ascii_case("Content-Length")
{
content_length = Some(value.trim().parse::<usize>().map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "invalid LSP Content-Length")
})?);
}
}
let length = content_length
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "missing LSP Content-Length"))?;
let mut body = vec![0; length];
reader.read_exact(&mut body)?;
serde_json::from_slice(&body)
.map(Some)
.map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))
}
fn write_message(writer: &mut impl Write, message: &Value) -> io::Result<()> {
let body = serde_json::to_vec(message).map_err(io::Error::other)?;
write!(writer, "Content-Length: {}\r\n\r\n", body.len())?;
writer.write_all(&body)
}
#[cfg(test)]
mod tests {
use std::io::{BufReader, Cursor};
use serde_json::json;
use super::*;
#[test]
fn reads_and_writes_lsp_content_length_frames() {
let message = json!({ "jsonrpc": "2.0", "id": 1, "method": "shutdown" });
let mut encoded = Vec::new();
write_message(&mut encoded, &message).unwrap();
let mut reader = BufReader::new(Cursor::new(encoded));
assert_eq!(read_message(&mut reader).unwrap(), Some(message));
assert_eq!(read_message(&mut reader).unwrap(), None);
}
}