aboutsummaryrefslogtreecommitdiff
path: root/crates/proc_macro_api/src/msg.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/proc_macro_api/src/msg.rs')
-rw-r--r--crates/proc_macro_api/src/msg.rs89
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
3use std::{
4 convert::TryFrom,
5 io::{self, BufRead, Write},
6};
7
8use serde::{de::DeserializeOwned, Deserialize, Serialize};
9
10use crate::{
11 rpc::{ListMacrosResult, ListMacrosTask},
12 ExpansionResult, ExpansionTask,
13};
14
15#[derive(Debug, Serialize, Deserialize, Clone)]
16pub enum Request {
17 ListMacro(ListMacrosTask),
18 ExpansionMacro(ExpansionTask),
19}
20
21#[derive(Debug, Serialize, Deserialize, Clone)]
22pub enum Response {
23 Error(ResponseError),
24 ListMacro(ListMacrosResult),
25 ExpansionMacro(ExpansionResult),
26}
27
28macro_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
42impl_try_from_response!(ListMacrosResult, ListMacro);
43impl_try_from_response!(ExpansionResult, ExpansionMacro);
44
45#[derive(Debug, Serialize, Deserialize, Clone)]
46pub struct ResponseError {
47 pub code: ErrorCode,
48 pub message: String,
49}
50
51#[derive(Debug, Serialize, Deserialize, Clone)]
52pub enum ErrorCode {
53 ServerErrorEnd,
54 ExpansionError,
55}
56
57pub 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
70impl Message for Request {}
71impl Message for Response {}
72
73fn 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
83fn 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}