diff options
author | Aleksey Kladov <[email protected]> | 2018-09-01 14:18:02 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-09-01 14:18:02 +0100 |
commit | 3588d6b2da6e63730cc560c9986ba7fda5de816e (patch) | |
tree | beb948f7527836c2c3e1c4b9dcc2dd2a79a16abf /crates/gen_lsp_server/src/msg.rs | |
parent | f5669dfc56b2b64d79f368eefed13dd75a6f027b (diff) |
add gen_lsp_server
Diffstat (limited to 'crates/gen_lsp_server/src/msg.rs')
-rw-r--r-- | crates/gen_lsp_server/src/msg.rs | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/crates/gen_lsp_server/src/msg.rs b/crates/gen_lsp_server/src/msg.rs new file mode 100644 index 000000000..9426e98ec --- /dev/null +++ b/crates/gen_lsp_server/src/msg.rs | |||
@@ -0,0 +1,172 @@ | |||
1 | use std::io::{BufRead, Write}; | ||
2 | |||
3 | use serde_json::{Value, from_str, to_string, from_value, to_value}; | ||
4 | use serde::{Serialize, de::DeserializeOwned}; | ||
5 | use languageserver_types::{ | ||
6 | request::Request, | ||
7 | notification::Notification, | ||
8 | }; | ||
9 | |||
10 | use Result; | ||
11 | |||
12 | #[derive(Debug, Serialize, Deserialize)] | ||
13 | #[serde(untagged)] | ||
14 | pub enum RawMessage { | ||
15 | Request(RawRequest), | ||
16 | Notification(RawNotification), | ||
17 | Response(RawResponse), | ||
18 | } | ||
19 | |||
20 | #[derive(Debug, Serialize, Deserialize)] | ||
21 | pub struct RawRequest { | ||
22 | pub id: u64, | ||
23 | pub method: String, | ||
24 | pub params: Value, | ||
25 | } | ||
26 | |||
27 | #[derive(Debug, Serialize, Deserialize)] | ||
28 | pub struct RawResponse { | ||
29 | // JSON RPC allows this to be null if it was impossible | ||
30 | // to decode the request's id. Ignore this special case | ||
31 | // and just die horribly. | ||
32 | pub id: u64, | ||
33 | #[serde(skip_serializing_if = "Option::is_none")] | ||
34 | pub result: Option<Value>, | ||
35 | #[serde(skip_serializing_if = "Option::is_none")] | ||
36 | pub error: Option<RawResponseError>, | ||
37 | } | ||
38 | |||
39 | #[derive(Debug, Serialize, Deserialize)] | ||
40 | pub struct RawResponseError { | ||
41 | pub code: i32, | ||
42 | pub message: String, | ||
43 | #[serde(skip_serializing_if = "Option::is_none")] | ||
44 | pub data: Option<Value>, | ||
45 | } | ||
46 | |||
47 | #[allow(unused)] | ||
48 | pub enum ErrorCode { | ||
49 | ParseError = -32700, | ||
50 | InvalidRequest = -32600, | ||
51 | MethodNotFound = -32601, | ||
52 | InvalidParams = -32602, | ||
53 | InternalError = -32603, | ||
54 | ServerErrorStart = -32099, | ||
55 | ServerErrorEnd = -32000, | ||
56 | ServerNotInitialized = -32002, | ||
57 | UnknownErrorCode = -32001, | ||
58 | RequestCancelled = -32800, | ||
59 | } | ||
60 | |||
61 | #[derive(Debug, Serialize, Deserialize)] | ||
62 | pub struct RawNotification { | ||
63 | pub method: String, | ||
64 | pub params: Value, | ||
65 | } | ||
66 | |||
67 | impl RawMessage { | ||
68 | pub fn read(r: &mut impl BufRead) -> Result<Option<RawMessage>> { | ||
69 | let text = match read_msg_text(r)? { | ||
70 | None => return Ok(None), | ||
71 | Some(text) => text, | ||
72 | }; | ||
73 | let msg = from_str(&text)?; | ||
74 | Ok(Some(msg)) | ||
75 | } | ||
76 | pub fn write(self, w: &mut impl Write) -> Result<()> { | ||
77 | #[derive(Serialize)] | ||
78 | struct JsonRpc { | ||
79 | jsonrpc: &'static str, | ||
80 | #[serde(flatten)] | ||
81 | msg: RawMessage, | ||
82 | } | ||
83 | let text = to_string(&JsonRpc { jsonrpc: "2.0", msg: self })?; | ||
84 | write_msg_text(w, &text)?; | ||
85 | Ok(()) | ||
86 | } | ||
87 | } | ||
88 | |||
89 | impl RawRequest { | ||
90 | pub fn cast<R>(self) -> ::std::result::Result<(u64, R::Params), RawRequest> | ||
91 | where | ||
92 | R: Request, | ||
93 | R::Params: DeserializeOwned, | ||
94 | { | ||
95 | if self.method != R::METHOD { | ||
96 | return Err(self); | ||
97 | } | ||
98 | let id = self.id; | ||
99 | let params: R::Params = from_value(self.params).unwrap(); | ||
100 | Ok((id, params)) | ||
101 | } | ||
102 | } | ||
103 | |||
104 | impl RawResponse { | ||
105 | pub fn ok(id: u64, result: impl Serialize) -> RawResponse { | ||
106 | RawResponse { | ||
107 | id, | ||
108 | result: Some(to_value(&result).unwrap()), | ||
109 | error: None, | ||
110 | } | ||
111 | } | ||
112 | pub fn err(id: u64, code: i32, message: String) -> RawResponse { | ||
113 | let error = RawResponseError { code, message, data: None }; | ||
114 | RawResponse { | ||
115 | id, | ||
116 | result: None, | ||
117 | error: Some(error), | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | impl RawNotification { | ||
123 | pub fn cast<N>(self) -> ::std::result::Result<N::Params, RawNotification> | ||
124 | where | ||
125 | N: Notification, | ||
126 | N::Params: DeserializeOwned, | ||
127 | { | ||
128 | if self.method != N::METHOD { | ||
129 | return Err(self); | ||
130 | } | ||
131 | Ok(from_value(self.params).unwrap()) | ||
132 | } | ||
133 | } | ||
134 | |||
135 | fn read_msg_text(inp: &mut impl BufRead) -> Result<Option<String>> { | ||
136 | let mut size = None; | ||
137 | let mut buf = String::new(); | ||
138 | loop { | ||
139 | buf.clear(); | ||
140 | if inp.read_line(&mut buf)? == 0 { | ||
141 | return Ok(None); | ||
142 | } | ||
143 | if !buf.ends_with("\r\n") { | ||
144 | bail!("malformed header: {:?}", buf); | ||
145 | } | ||
146 | let buf = &buf[..buf.len() - 2]; | ||
147 | if buf.is_empty() { | ||
148 | break; | ||
149 | } | ||
150 | let mut parts = buf.splitn(2, ": "); | ||
151 | let header_name = parts.next().unwrap(); | ||
152 | let header_value = parts.next().ok_or_else(|| format_err!("malformed header: {:?}", buf))?; | ||
153 | if header_name == "Content-Length" { | ||
154 | size = Some(header_value.parse::<usize>()?); | ||
155 | } | ||
156 | } | ||
157 | let size = size.ok_or_else(|| format_err!("no Content-Length"))?; | ||
158 | let mut buf = buf.into_bytes(); | ||
159 | buf.resize(size, 0); | ||
160 | inp.read_exact(&mut buf)?; | ||
161 | let buf = String::from_utf8(buf)?; | ||
162 | debug!("< {}", buf); | ||
163 | Ok(Some(buf)) | ||
164 | } | ||
165 | |||
166 | fn write_msg_text(out: &mut impl Write, msg: &str) -> Result<()> { | ||
167 | debug!("> {}", msg); | ||
168 | write!(out, "Content-Length: {}\r\n\r\n", msg.len())?; | ||
169 | out.write_all(msg.as_bytes())?; | ||
170 | out.flush()?; | ||
171 | Ok(()) | ||
172 | } | ||