diff options
author | Zac Pullar-Strecker <[email protected]> | 2020-08-24 10:19:53 +0100 |
---|---|---|
committer | Zac Pullar-Strecker <[email protected]> | 2020-08-24 10:20:13 +0100 |
commit | 7bbca7a1b3f9293d2f5cc5745199bc5f8396f2f0 (patch) | |
tree | bdb47765991cb973b2cd5481a088fac636bd326c /crates/proc_macro_api/src/msg.rs | |
parent | ca464650eeaca6195891199a93f4f76cf3e7e697 (diff) | |
parent | e65d48d1fb3d4d91d9dc1148a7a836ff5c9a3c87 (diff) |
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Diffstat (limited to 'crates/proc_macro_api/src/msg.rs')
-rw-r--r-- | crates/proc_macro_api/src/msg.rs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/crates/proc_macro_api/src/msg.rs b/crates/proc_macro_api/src/msg.rs new file mode 100644 index 000000000..f84ebdbc5 --- /dev/null +++ b/crates/proc_macro_api/src/msg.rs | |||
@@ -0,0 +1,89 @@ | |||
1 | //! Defines messages for cross-process message passing based on `ndjson` wire protocol | ||
2 | |||
3 | use std::{ | ||
4 | convert::TryFrom, | ||
5 | io::{self, BufRead, Write}, | ||
6 | }; | ||
7 | |||
8 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; | ||
9 | |||
10 | use crate::{ | ||
11 | rpc::{ListMacrosResult, ListMacrosTask}, | ||
12 | ExpansionResult, ExpansionTask, | ||
13 | }; | ||
14 | |||
15 | #[derive(Debug, Serialize, Deserialize, Clone)] | ||
16 | pub enum Request { | ||
17 | ListMacro(ListMacrosTask), | ||
18 | ExpansionMacro(ExpansionTask), | ||
19 | } | ||
20 | |||
21 | #[derive(Debug, Serialize, Deserialize, Clone)] | ||
22 | pub enum Response { | ||
23 | Error(ResponseError), | ||
24 | ListMacro(ListMacrosResult), | ||
25 | ExpansionMacro(ExpansionResult), | ||
26 | } | ||
27 | |||
28 | macro_rules! impl_try_from_response { | ||
29 | ($ty:ty, $tag:ident) => { | ||
30 | impl TryFrom<Response> for $ty { | ||
31 | type Error = &'static str; | ||
32 | fn try_from(value: Response) -> Result<Self, Self::Error> { | ||
33 | match value { | ||
34 | Response::$tag(res) => Ok(res), | ||
35 | _ => Err(concat!("Failed to convert response to ", stringify!($tag))), | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | }; | ||
40 | } | ||
41 | |||
42 | impl_try_from_response!(ListMacrosResult, ListMacro); | ||
43 | impl_try_from_response!(ExpansionResult, ExpansionMacro); | ||
44 | |||
45 | #[derive(Debug, Serialize, Deserialize, Clone)] | ||
46 | pub struct ResponseError { | ||
47 | pub code: ErrorCode, | ||
48 | pub message: String, | ||
49 | } | ||
50 | |||
51 | #[derive(Debug, Serialize, Deserialize, Clone)] | ||
52 | pub enum ErrorCode { | ||
53 | ServerErrorEnd, | ||
54 | ExpansionError, | ||
55 | } | ||
56 | |||
57 | pub trait Message: Serialize + DeserializeOwned { | ||
58 | fn read(inp: &mut impl BufRead) -> io::Result<Option<Self>> { | ||
59 | Ok(match read_json(inp)? { | ||
60 | None => None, | ||
61 | Some(text) => Some(serde_json::from_str(&text)?), | ||
62 | }) | ||
63 | } | ||
64 | fn write(self, out: &mut impl Write) -> io::Result<()> { | ||
65 | let text = serde_json::to_string(&self)?; | ||
66 | write_json(out, &text) | ||
67 | } | ||
68 | } | ||
69 | |||
70 | impl Message for Request {} | ||
71 | impl Message for Response {} | ||
72 | |||
73 | fn read_json(inp: &mut impl BufRead) -> io::Result<Option<String>> { | ||
74 | let mut buf = String::new(); | ||
75 | inp.read_line(&mut buf)?; | ||
76 | buf.pop(); // Remove traling '\n' | ||
77 | Ok(match buf.len() { | ||
78 | 0 => None, | ||
79 | _ => Some(buf), | ||
80 | }) | ||
81 | } | ||
82 | |||
83 | fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { | ||
84 | log::debug!("> {}", msg); | ||
85 | out.write_all(msg.as_bytes())?; | ||
86 | out.write_all(b"\n")?; | ||
87 | out.flush()?; | ||
88 | Ok(()) | ||
89 | } | ||