aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_proc_macro/src/msg.rs
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2020-03-26 20:26:34 +0000
committerEdwin Cheng <[email protected]>2020-03-31 15:20:18 +0100
commit503cbd3f4b54f3be224d7a4221fa023f0e35d228 (patch)
tree101dcec6de8da790766a6e76d8f983242d8fcbfd /crates/ra_proc_macro/src/msg.rs
parentfa3c7742af9fbfe5146f4158a6119fa727dcc87a (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.rs218
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
3use std::{
4 fmt,
5 io::{self, BufRead, Write},
6};
7
8use serde::{de::DeserializeOwned, Deserialize, Serialize};
9
10#[derive(Serialize, Deserialize, Debug, Clone)]
11#[serde(untagged)]
12pub enum Message {
13 Request(Request),
14 Response(Response),
15}
16
17impl From<Request> for Message {
18 fn from(request: Request) -> Message {
19 Message::Request(request)
20 }
21}
22
23impl 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)]
31pub struct RequestId(IdRepr);
32
33#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
34#[serde(untagged)]
35enum IdRepr {
36 U64(u64),
37 String(String),
38}
39
40impl From<u64> for RequestId {
41 fn from(id: u64) -> RequestId {
42 RequestId(IdRepr::U64(id))
43 }
44}
45
46impl From<String> for RequestId {
47 fn from(id: String) -> RequestId {
48 RequestId(IdRepr::String(id))
49 }
50}
51
52impl 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)]
62pub struct Request {
63 pub id: RequestId,
64 pub method: String,
65 pub params: serde_json::Value,
66}
67
68#[derive(Debug, Serialize, Deserialize, Clone)]
69pub 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)]
81pub 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)]
90pub 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)]
107pub struct Notification {
108 pub method: String,
109 pub params: serde_json::Value,
110}
111
112impl 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
133impl 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
143impl 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
159impl 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
173fn 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
212fn 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}