aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2020-03-28 10:12:51 +0000
committerEdwin Cheng <[email protected]>2020-03-31 15:20:18 +0100
commit0aacacd4a2ece0801287cf3e8f3f7c9115f6b548 (patch)
tree922d9440f7bf8449adb5a05bc03a22e0805e0824 /crates
parent7155d5df89e6b36018f8844774c4164eba64b49f (diff)
Simple cross-process message protocol
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_proc_macro/src/msg.rs231
-rw-r--r--crates/ra_proc_macro/src/process.rs74
-rw-r--r--crates/ra_proc_macro/src/rpc.rs6
3 files changed, 86 insertions, 225 deletions
diff --git a/crates/ra_proc_macro/src/msg.rs b/crates/ra_proc_macro/src/msg.rs
index 2fb065d32..aa95bcc8f 100644
--- a/crates/ra_proc_macro/src/msg.rs
+++ b/crates/ra_proc_macro/src/msg.rs
@@ -1,218 +1,93 @@
1//! A simplified version of lsp base protocol for rpc 1//! Defines messages for cross-process message based on `ndjson` wire protocol
2 2
3use std::{ 3use std::{
4 fmt, 4 convert::TryFrom,
5 io::{self, BufRead, Write}, 5 io::{self, BufRead, Write},
6}; 6};
7 7
8use crate::{
9 rpc::{ListMacrosResult, ListMacrosTask},
10 ExpansionResult, ExpansionTask,
11};
8use serde::{de::DeserializeOwned, Deserialize, Serialize}; 12use serde::{de::DeserializeOwned, Deserialize, Serialize};
9 13
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)] 14#[derive(Debug, Serialize, Deserialize, Clone)]
62pub struct Request { 15pub enum Request {
63 pub id: RequestId, 16 ListMacro(ListMacrosTask),
64 pub method: String, 17 ExpansionMacro(ExpansionTask),
65 pub params: serde_json::Value,
66} 18}
67 19
68#[derive(Debug, Serialize, Deserialize, Clone)] 20#[derive(Debug, Serialize, Deserialize, Clone)]
69pub struct Response { 21pub enum Response {
70 // JSON RPC allows this to be null if it was impossible 22 Error(ResponseError),
71 // to decode the request's id. Ignore this special case 23 ListMacro(ListMacrosResult),
72 // and just die horribly. 24 ExpansionMacro(ExpansionResult),
73 pub id: RequestId, 25}
74 #[serde(skip_serializing_if = "Option::is_none")] 26
75 pub result: Option<serde_json::Value>, 27macro_rules! impl_try_from_response {
76 #[serde(skip_serializing_if = "Option::is_none")] 28 ($ty:ty, $tag:ident) => {
77 pub error: Option<ResponseError>, 29 impl TryFrom<Response> for $ty {
30 type Error = &'static str;
31 fn try_from(value: Response) -> Result<Self, Self::Error> {
32 match value {
33 Response::$tag(res) => Ok(res),
34 _ => Err("Fail to convert from response"),
35 }
36 }
37 }
38 };
78} 39}
79 40
41impl_try_from_response!(ListMacrosResult, ListMacro);
42impl_try_from_response!(ExpansionResult, ExpansionMacro);
43
80#[derive(Debug, Serialize, Deserialize, Clone)] 44#[derive(Debug, Serialize, Deserialize, Clone)]
81pub struct ResponseError { 45pub struct ResponseError {
82 pub code: i32, 46 pub code: ErrorCode,
83 pub message: String, 47 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} 48}
105 49
106#[derive(Debug, Serialize, Deserialize, Clone)] 50#[derive(Debug, Serialize, Deserialize, Clone)]
107pub struct Notification { 51pub enum ErrorCode {
108 pub method: String, 52 ServerErrorEnd,
109 pub params: serde_json::Value, 53 ExpansionError,
110} 54}
111 55
112impl Message { 56pub trait Message: Sized + Serialize + DeserializeOwned {
113 pub fn read(r: &mut impl BufRead) -> io::Result<Option<Message>> { 57 fn read(r: &mut impl BufRead) -> io::Result<Option<Self>> {
114 let text = match read_msg_text(r)? { 58 let text = match read_json(r)? {
115 None => return Ok(None), 59 None => return Ok(None),
116 Some(text) => text, 60 Some(text) => text,
117 }; 61 };
118 let msg = serde_json::from_str(&text)?; 62 let msg = serde_json::from_str(&text)?;
119 Ok(Some(msg)) 63 Ok(Some(msg))
120 } 64 }
121 pub fn write(self, w: &mut impl Write) -> io::Result<()> { 65 fn write(self, w: &mut impl Write) -> io::Result<()> {
122 #[derive(Serialize)] 66 let text = serde_json::to_string(&self)?;
123 struct JsonRpc { 67 write_json(w, &text)
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 } 68 }
131} 69}
132 70
133impl Response { 71impl Message for Request {}
134 pub fn new_ok<R: Serialize>(id: RequestId, result: R) -> Response { 72impl Message for 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 73
143impl Request { 74fn read_json(inp: &mut impl BufRead) -> io::Result<Option<String>> {
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(); 75 let mut buf = String::new();
183 loop { 76 if inp.read_line(&mut buf)? == 0 {
184 buf.clear(); 77 return Ok(None);
185 if inp.read_line(&mut buf)? == 0 { 78 }
186 return Ok(None); 79 // Remove ending '\n'
187 } 80 let buf = &buf[..buf.len() - 1];
188 if !buf.ends_with("\r\n") { 81 if buf.is_empty() {
189 return Err(invalid_data!("malformed header: {:?}", buf)); 82 return Ok(None);
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 } 83 }
203 let size: usize = size.ok_or_else(|| invalid_data!("no Content-Length"))?; 84 Ok(Some(buf.to_string()))
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} 85}
211 86
212fn write_msg_text(out: &mut impl Write, msg: &str) -> io::Result<()> { 87fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> {
213 log::debug!("> {}", msg); 88 log::debug!("> {}", msg);
214 write!(out, "Content-Length: {}\r\n\r\n", msg.len())?;
215 out.write_all(msg.as_bytes())?; 89 out.write_all(msg.as_bytes())?;
90 out.write_all(b"\n")?;
216 out.flush()?; 91 out.flush()?;
217 Ok(()) 92 Ok(())
218} 93}
diff --git a/crates/ra_proc_macro/src/process.rs b/crates/ra_proc_macro/src/process.rs
index daae9a7e0..2b1f8535a 100644
--- a/crates/ra_proc_macro/src/process.rs
+++ b/crates/ra_proc_macro/src/process.rs
@@ -3,11 +3,12 @@
3use crossbeam_channel::{bounded, Receiver, Sender}; 3use crossbeam_channel::{bounded, Receiver, Sender};
4use ra_tt::Subtree; 4use ra_tt::Subtree;
5 5
6use crate::msg::{ErrorCode, Message, Request, Response, ResponseError}; 6use crate::msg::{ErrorCode, Request, Response, ResponseError, Message};
7use crate::rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind}; 7use crate::rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind};
8 8
9use io::{BufRead, BufReader}; 9use io::{BufRead, BufReader};
10use std::{ 10use std::{
11 convert::{TryFrom, TryInto},
11 io::{self, Write}, 12 io::{self, Write},
12 path::{Path, PathBuf}, 13 path::{Path, PathBuf},
13 process::{Child, Command, Stdio}, 14 process::{Child, Command, Stdio},
@@ -26,7 +27,7 @@ pub(crate) struct ProcMacroProcessThread {
26} 27}
27 28
28enum Task { 29enum Task {
29 Request { req: Message, result_tx: Sender<Message> }, 30 Request { req: Request, result_tx: Sender<Response> },
30 Close, 31 Close,
31} 32}
32 33
@@ -96,7 +97,7 @@ impl ProcMacroProcessSrv {
96 ) -> Result<Vec<(String, ProcMacroKind)>, ra_tt::ExpansionError> { 97 ) -> Result<Vec<(String, ProcMacroKind)>, ra_tt::ExpansionError> {
97 let task = ListMacrosTask { lib: dylib_path.to_path_buf() }; 98 let task = ListMacrosTask { lib: dylib_path.to_path_buf() };
98 99
99 let result: ListMacrosResult = self.send_task("list_macros", task)?; 100 let result: ListMacrosResult = self.send_task(Request::ListMacro(task))?;
100 Ok(result.macros) 101 Ok(result.macros)
101 } 102 }
102 103
@@ -113,26 +114,19 @@ impl ProcMacroProcessSrv {
113 lib: dylib_path.to_path_buf(), 114 lib: dylib_path.to_path_buf(),
114 }; 115 };
115 116
116 let result: ExpansionResult = self.send_task("custom_derive", task)?; 117 let result: ExpansionResult = self.send_task(Request::ExpansionMacro(task))?;
117 Ok(result.expansion) 118 Ok(result.expansion)
118 } 119 }
119 120
120 pub fn send_task<'a, T, R>(&self, method: &str, task: T) -> Result<R, ra_tt::ExpansionError> 121 pub fn send_task<R>(&self, req: Request) -> Result<R, ra_tt::ExpansionError>
121 where 122 where
122 T: serde::Serialize, 123 R: TryFrom<Response, Error = &'static str>,
123 R: serde::de::DeserializeOwned + Default,
124 { 124 {
125 let sender = match &self.inner { 125 let sender = match &self.inner {
126 None => return Err(ra_tt::ExpansionError::Unknown("No sender is found.".to_string())), 126 None => return Err(ra_tt::ExpansionError::Unknown("No sender is found.".to_string())),
127 Some(it) => it, 127 Some(it) => it,
128 }; 128 };
129 129
130 let msg = serde_json::to_value(task).unwrap();
131
132 // FIXME: use a proper request id
133 let id = 0;
134 let req = Request { id: id.into(), method: method.into(), params: msg };
135
136 let (result_tx, result_rx) = bounded(0); 130 let (result_tx, result_rx) = bounded(0);
137 131
138 sender.send(Task::Request { req: req.into(), result_tx }).map_err(|err| { 132 sender.send(Task::Request { req: req.into(), result_tx }).map_err(|err| {
@@ -141,27 +135,18 @@ impl ProcMacroProcessSrv {
141 err 135 err
142 )) 136 ))
143 })?; 137 })?;
144 let response = result_rx.recv().unwrap();
145 138
146 match response { 139 let res = result_rx.recv().unwrap();
147 Message::Request(_) => { 140 match res {
148 return Err(ra_tt::ExpansionError::Unknown( 141 Response::Error(err) => {
149 "Return request from ra_proc_srv".into(), 142 return Err(ra_tt::ExpansionError::ExpansionError(err.message));
150 ))
151 }
152 Message::Response(res) => {
153 if let Some(err) = res.error {
154 return Err(ra_tt::ExpansionError::ExpansionError(err.message));
155 }
156 match res.result {
157 None => Ok(R::default()),
158 Some(res) => {
159 let result: R = serde_json::from_value(res)
160 .map_err(|err| ra_tt::ExpansionError::JsonError(err.to_string()))?;
161 Ok(result)
162 }
163 }
164 } 143 }
144 _ => Ok(res.try_into().map_err(|err| {
145 ra_tt::ExpansionError::Unknown(format!(
146 "Fail to get response, reason : {:#?} ",
147 err
148 ))
149 })?),
165 } 150 }
166 } 151 }
167} 152}
@@ -183,18 +168,13 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
183 Task::Close => break, 168 Task::Close => break,
184 }; 169 };
185 170
186 let res = match send_message(&mut stdin, &mut stdout, req) { 171 let res = match send_request(&mut stdin, &mut stdout, req) {
187 Ok(res) => res, 172 Ok(res) => res,
188 Err(_err) => { 173 Err(_err) => {
189 let res = Response { 174 let res = Response::Error(ResponseError {
190 id: 0.into(), 175 code: ErrorCode::ServerErrorEnd,
191 result: None, 176 message: "Server closed".into(),
192 error: Some(ResponseError { 177 });
193 code: ErrorCode::ServerErrorEnd as i32,
194 message: "Server closed".into(),
195 data: None,
196 }),
197 };
198 if result_tx.send(res.into()).is_err() { 178 if result_tx.send(res.into()).is_err() {
199 break; 179 break;
200 } 180 }
@@ -222,11 +202,11 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
222 let _ = process.child.kill(); 202 let _ = process.child.kill();
223} 203}
224 204
225fn send_message( 205fn send_request(
226 mut writer: &mut impl Write, 206 mut writer: &mut impl Write,
227 mut reader: &mut impl BufRead, 207 mut reader: &mut impl BufRead,
228 msg: Message, 208 req: Request,
229) -> Result<Option<Message>, io::Error> { 209) -> Result<Option<Response>, io::Error> {
230 msg.write(&mut writer)?; 210 req.write(&mut writer)?;
231 Ok(Message::read(&mut reader)?) 211 Ok(Response::read(&mut reader)?)
232} 212}
diff --git a/crates/ra_proc_macro/src/rpc.rs b/crates/ra_proc_macro/src/rpc.rs
index f88d91f78..fc8b04e28 100644
--- a/crates/ra_proc_macro/src/rpc.rs
+++ b/crates/ra_proc_macro/src/rpc.rs
@@ -1,4 +1,10 @@
1//! Data struture serialization related stuffs for RPC 1//! Data struture serialization related stuffs for RPC
2//!
3//! Define all necessary rpc serialization data structure,
4//! which include ra_tt related data and some task messages.
5//! Although adding Serialize and Deserialize trait to ra_tt directly seem to be much easier,
6//! we deliberately duplicate the ra_tt struct with #[serde(with = "XXDef")]
7//! for separation of code responsibility.
2 8
3use ra_tt::{ 9use ra_tt::{
4 Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, SmolStr, Spacing, Subtree, TokenId, 10 Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, SmolStr, Spacing, Subtree, TokenId,