diff options
author | Edwin Cheng <[email protected]> | 2020-03-26 20:26:34 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2020-03-31 15:20:18 +0100 |
commit | 503cbd3f4b54f3be224d7a4221fa023f0e35d228 (patch) | |
tree | 101dcec6de8da790766a6e76d8f983242d8fcbfd /crates/ra_proc_macro/src/msg.rs | |
parent | fa3c7742af9fbfe5146f4158a6119fa727dcc87a (diff) |
Implement ra_proc_macro client logic
Diffstat (limited to 'crates/ra_proc_macro/src/msg.rs')
-rw-r--r-- | crates/ra_proc_macro/src/msg.rs | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/crates/ra_proc_macro/src/msg.rs b/crates/ra_proc_macro/src/msg.rs new file mode 100644 index 000000000..2fb065d32 --- /dev/null +++ b/crates/ra_proc_macro/src/msg.rs | |||
@@ -0,0 +1,218 @@ | |||
1 | //! A simplified version of lsp base protocol for rpc | ||
2 | |||
3 | use std::{ | ||
4 | fmt, | ||
5 | io::{self, BufRead, Write}, | ||
6 | }; | ||
7 | |||
8 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; | ||
9 | |||
10 | #[derive(Serialize, Deserialize, Debug, Clone)] | ||
11 | #[serde(untagged)] | ||
12 | pub enum Message { | ||
13 | Request(Request), | ||
14 | Response(Response), | ||
15 | } | ||
16 | |||
17 | impl From<Request> for Message { | ||
18 | fn from(request: Request) -> Message { | ||
19 | Message::Request(request) | ||
20 | } | ||
21 | } | ||
22 | |||
23 | impl From<Response> for Message { | ||
24 | fn from(response: Response) -> Message { | ||
25 | Message::Response(response) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
30 | #[serde(transparent)] | ||
31 | pub struct RequestId(IdRepr); | ||
32 | |||
33 | #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
34 | #[serde(untagged)] | ||
35 | enum IdRepr { | ||
36 | U64(u64), | ||
37 | String(String), | ||
38 | } | ||
39 | |||
40 | impl From<u64> for RequestId { | ||
41 | fn from(id: u64) -> RequestId { | ||
42 | RequestId(IdRepr::U64(id)) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | impl From<String> for RequestId { | ||
47 | fn from(id: String) -> RequestId { | ||
48 | RequestId(IdRepr::String(id)) | ||
49 | } | ||
50 | } | ||
51 | |||
52 | impl fmt::Display for RequestId { | ||
53 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
54 | match &self.0 { | ||
55 | IdRepr::U64(it) => fmt::Display::fmt(it, f), | ||
56 | IdRepr::String(it) => fmt::Display::fmt(it, f), | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | |||
61 | #[derive(Debug, Serialize, Deserialize, Clone)] | ||
62 | pub struct Request { | ||
63 | pub id: RequestId, | ||
64 | pub method: String, | ||
65 | pub params: serde_json::Value, | ||
66 | } | ||
67 | |||
68 | #[derive(Debug, Serialize, Deserialize, Clone)] | ||
69 | pub struct Response { | ||
70 | // JSON RPC allows this to be null if it was impossible | ||
71 | // to decode the request's id. Ignore this special case | ||
72 | // and just die horribly. | ||
73 | pub id: RequestId, | ||
74 | #[serde(skip_serializing_if = "Option::is_none")] | ||
75 | pub result: Option<serde_json::Value>, | ||
76 | #[serde(skip_serializing_if = "Option::is_none")] | ||
77 | pub error: Option<ResponseError>, | ||
78 | } | ||
79 | |||
80 | #[derive(Debug, Serialize, Deserialize, Clone)] | ||
81 | pub struct ResponseError { | ||
82 | pub code: i32, | ||
83 | pub message: String, | ||
84 | #[serde(skip_serializing_if = "Option::is_none")] | ||
85 | pub data: Option<serde_json::Value>, | ||
86 | } | ||
87 | |||
88 | #[derive(Clone, Copy, Debug)] | ||
89 | #[allow(unused)] | ||
90 | pub enum ErrorCode { | ||
91 | // Defined by JSON RPC | ||
92 | ParseError = -32700, | ||
93 | InvalidRequest = -32600, | ||
94 | MethodNotFound = -32601, | ||
95 | InvalidParams = -32602, | ||
96 | InternalError = -32603, | ||
97 | ServerErrorStart = -32099, | ||
98 | ServerErrorEnd = -32000, | ||
99 | ServerNotInitialized = -32002, | ||
100 | UnknownErrorCode = -32001, | ||
101 | |||
102 | // Defined by protocol | ||
103 | ExpansionError = -32900, | ||
104 | } | ||
105 | |||
106 | #[derive(Debug, Serialize, Deserialize, Clone)] | ||
107 | pub struct Notification { | ||
108 | pub method: String, | ||
109 | pub params: serde_json::Value, | ||
110 | } | ||
111 | |||
112 | impl Message { | ||
113 | pub fn read(r: &mut impl BufRead) -> io::Result<Option<Message>> { | ||
114 | let text = match read_msg_text(r)? { | ||
115 | None => return Ok(None), | ||
116 | Some(text) => text, | ||
117 | }; | ||
118 | let msg = serde_json::from_str(&text)?; | ||
119 | Ok(Some(msg)) | ||
120 | } | ||
121 | pub fn write(self, w: &mut impl Write) -> io::Result<()> { | ||
122 | #[derive(Serialize)] | ||
123 | struct JsonRpc { | ||
124 | jsonrpc: &'static str, | ||
125 | #[serde(flatten)] | ||
126 | msg: Message, | ||
127 | } | ||
128 | let text = serde_json::to_string(&JsonRpc { jsonrpc: "2.0", msg: self })?; | ||
129 | write_msg_text(w, &text) | ||
130 | } | ||
131 | } | ||
132 | |||
133 | impl Response { | ||
134 | pub fn new_ok<R: Serialize>(id: RequestId, result: R) -> Response { | ||
135 | Response { id, result: Some(serde_json::to_value(result).unwrap()), error: None } | ||
136 | } | ||
137 | pub fn new_err(id: RequestId, code: i32, message: String) -> Response { | ||
138 | let error = ResponseError { code, message, data: None }; | ||
139 | Response { id, result: None, error: Some(error) } | ||
140 | } | ||
141 | } | ||
142 | |||
143 | impl Request { | ||
144 | pub fn new<P: Serialize>(id: RequestId, method: String, params: P) -> Request { | ||
145 | Request { id, method, params: serde_json::to_value(params).unwrap() } | ||
146 | } | ||
147 | pub fn extract<P: DeserializeOwned>(self, method: &str) -> Result<(RequestId, P), Request> { | ||
148 | if self.method == method { | ||
149 | let params = serde_json::from_value(self.params).unwrap_or_else(|err| { | ||
150 | panic!("Invalid request\nMethod: {}\n error: {}", method, err) | ||
151 | }); | ||
152 | Ok((self.id, params)) | ||
153 | } else { | ||
154 | Err(self) | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | |||
159 | impl Notification { | ||
160 | pub fn new(method: String, params: impl Serialize) -> Notification { | ||
161 | Notification { method, params: serde_json::to_value(params).unwrap() } | ||
162 | } | ||
163 | pub fn extract<P: DeserializeOwned>(self, method: &str) -> Result<P, Notification> { | ||
164 | if self.method == method { | ||
165 | let params = serde_json::from_value(self.params).unwrap(); | ||
166 | Ok(params) | ||
167 | } else { | ||
168 | Err(self) | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | |||
173 | fn read_msg_text(inp: &mut impl BufRead) -> io::Result<Option<String>> { | ||
174 | fn invalid_data(error: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error { | ||
175 | io::Error::new(io::ErrorKind::InvalidData, error) | ||
176 | } | ||
177 | macro_rules! invalid_data { | ||
178 | ($($tt:tt)*) => (invalid_data(format!($($tt)*))) | ||
179 | } | ||
180 | |||
181 | let mut size = None; | ||
182 | let mut buf = String::new(); | ||
183 | loop { | ||
184 | buf.clear(); | ||
185 | if inp.read_line(&mut buf)? == 0 { | ||
186 | return Ok(None); | ||
187 | } | ||
188 | if !buf.ends_with("\r\n") { | ||
189 | return Err(invalid_data!("malformed header: {:?}", buf)); | ||
190 | } | ||
191 | let buf = &buf[..buf.len() - 2]; | ||
192 | if buf.is_empty() { | ||
193 | break; | ||
194 | } | ||
195 | let mut parts = buf.splitn(2, ": "); | ||
196 | let header_name = parts.next().unwrap(); | ||
197 | let header_value = | ||
198 | parts.next().ok_or_else(|| invalid_data!("malformed header: {:?}", buf))?; | ||
199 | if header_name == "Content-Length" { | ||
200 | size = Some(header_value.parse::<usize>().map_err(invalid_data)?); | ||
201 | } | ||
202 | } | ||
203 | let size: usize = size.ok_or_else(|| invalid_data!("no Content-Length"))?; | ||
204 | let mut buf = buf.into_bytes(); | ||
205 | buf.resize(size, 0); | ||
206 | inp.read_exact(&mut buf)?; | ||
207 | let buf = String::from_utf8(buf).map_err(invalid_data)?; | ||
208 | log::debug!("< {}", buf); | ||
209 | Ok(Some(buf)) | ||
210 | } | ||
211 | |||
212 | fn write_msg_text(out: &mut impl Write, msg: &str) -> io::Result<()> { | ||
213 | log::debug!("> {}", msg); | ||
214 | write!(out, "Content-Length: {}\r\n\r\n", msg.len())?; | ||
215 | out.write_all(msg.as_bytes())?; | ||
216 | out.flush()?; | ||
217 | Ok(()) | ||
218 | } | ||