1use crate::Notification;
2use crate::Request;
3use crate::Response;
4use serde::{Deserialize, Serialize};
5use std::io;
6
7#[derive(Serialize, Deserialize, Debug, Clone)]
8#[serde(untagged)]
9pub enum Message {
10 Request(Request),
11 Response(Response),
12 Notification(Notification),
13}
14
15#[derive(Serialize)]
16struct JsonRpc {
17 jsonrpc: &'static str,
18 #[serde(flatten)]
19 msg: Message,
20}
21
22impl From<Message> for JsonRpc {
23 fn from(msg: Message) -> Self {
24 Self {
25 jsonrpc: "2.0",
26 msg,
27 }
28 }
29}
30
31impl Message {
32 pub(crate) fn read(r: &mut dyn io::BufRead) -> io::Result<Option<Message>> {
33 let text = match read_msg_text(r)? {
34 Some(text) => text,
35 None => return Ok(None),
36 };
37 let msg = serde_json::from_str(&text)?;
38 tracing::trace!("Got <<<<<<<<<<<<<<<<<<<<<<<<<\n\n{:#?}\n", msg);
39 Ok(Some(msg))
40 }
41
42 pub(crate) fn write(self, w: &mut dyn io::Write) -> io::Result<()> {
43 tracing::trace!("Sent >>>>>>>>>>>>>>>>>>>>>>>>>\n\n{:#?}\n", self);
44 let msg = serde_json::to_string(&JsonRpc::from(self))?;
45 write!(w, "Content-Length: {}\r\n\r\n", msg.len())?;
46 w.write_all(msg.as_bytes())?;
47 w.flush()?;
48 Ok(())
49 }
50}
51
52fn invalid_data(error: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
53 io::Error::new(io::ErrorKind::InvalidData, error)
54}
55
56macro_rules! invalid_data { ($($tt:tt)*) => (invalid_data(format!($($tt)*))) }
57
58fn read_msg_text(inp: &mut dyn io::BufRead) -> io::Result<Option<String>> {
59 let mut size = None;
60 let mut buf = String::new();
61
62 loop {
63 buf.clear();
64 if inp.read_line(&mut buf)? == 0 {
65 return Ok(None);
66 }
67 if !buf.ends_with("\r\n") {
68 return Err(invalid_data!("malformed header: {:?}", buf));
69 }
70 let buf = &buf[..buf.len() - 2];
71 if buf.is_empty() {
72 break;
73 }
74 let mut parts = buf.splitn(2, ": ");
75 let header_name = parts.next().unwrap();
76 let header_value = parts
77 .next()
78 .ok_or_else(|| invalid_data!("malformed header: {:?}", buf))?;
79 if header_name == "Content-Length" {
80 size = Some(header_value.parse::<usize>().map_err(invalid_data)?);
81 }
82 }
83
84 let size: usize = size.ok_or_else(|| invalid_data!("no Content-Length"))?;
85 let mut buf = buf.into_bytes();
86
87 buf.resize(size, 0);
88 inp.read_exact(&mut buf)?;
89
90 Ok(Some(String::from_utf8(buf).map_err(invalid_data)?))
91}