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
|
use std::{
collections::HashMap,
process::{ChildStderr, ChildStdin, ChildStdout, Command, Stdio},
};
use smol::io::{BufReader, BufWriter};
use smol::prelude::*;
use smol::Unblock;
struct Client {
// process: Command,
reader: BufReader<Unblock<ChildStdout>>,
}
impl Client {
fn start(cmd: &str, args: &[String]) -> Self {
let mut process = Command::new(cmd)
.args(args)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("Failed to start language server");
// TODO: impl drop that kills the process
// TODO: do we need bufreader/writer here? or do we use async wrappers on unblock?
let writer = BufWriter::new(Unblock::new(
process.stdin.take().expect("Failed to open stdin"),
));
let reader = BufReader::new(Unblock::new(
process.stdout.take().expect("Failed to open stdout"),
));
let stderr = BufReader::new(Unblock::new(
process.stderr.take().expect("Failed to open stderr"),
));
Client { reader }
}
async fn receiver(&mut self) -> Result<(), std::io::Error> {
let mut headers: HashMap<String, String> = HashMap::default();
loop {
// read headers
loop {
let mut header = String::new();
// detect pipe closed if 0
self.reader.read_line(&mut header).await?;
let header = header.trim();
if header.is_empty() {
break;
}
let parts: Vec<&str> = header.split(": ").collect();
if parts.len() != 2 {
// return Err(Error::new(ErrorKind::Other, "Failed to parse header"));
panic!()
}
headers.insert(parts[0].to_string(), parts[1].to_string());
}
// find content-length
// read data
// decode via serde_json decoding into jsonrpc_core Output
break;
}
Ok(())
}
}
|