sync_ls/
dap.rs

1//! A synchronous debug adaptor server implementation.
2
3use std::io;
4
5use serde::{Deserialize, Serialize};
6
7pub use dapts::{Event, Request, Response};
8
9use crate::{LspOrDapResponse, invalid_data_fmt, read_msg_text, write_msg_text};
10
11/// A message in the Debug Adaptor Protocol.
12#[derive(Serialize, Deserialize, Debug, Clone)]
13#[serde(tag = "type")]
14pub enum Message {
15    /// Request messages
16    #[serde(rename = "request")]
17    Request(Request),
18    /// Response messages
19    #[serde(rename = "response")]
20    Response(Response),
21    /// Event messages
22    #[serde(rename = "event")]
23    Event(Event),
24}
25
26impl From<Request> for Message {
27    fn from(req: Request) -> Self {
28        Message::Request(req)
29    }
30}
31
32impl From<Response> for Message {
33    fn from(resp: Response) -> Self {
34        Message::Response(resp)
35    }
36}
37
38impl From<Event> for Message {
39    fn from(event: Event) -> Self {
40        Message::Event(event)
41    }
42}
43
44impl Message {
45    /// Reads a DAP message from the reader.
46    pub fn read(r: &mut impl io::BufRead) -> io::Result<Option<Message>> {
47        let text = match read_msg_text(r)? {
48            None => return Ok(None),
49            Some(text) => text,
50        };
51
52        let msg = match serde_json::from_str(&text) {
53            Ok(msg) => msg,
54            Err(e) => {
55                return Err(invalid_data_fmt!("malformed DAP payload: {e:?}"));
56            }
57        };
58
59        Ok(Some(msg))
60    }
61    /// Writes the DAP message to the writer.
62    pub fn write(self, w: &mut impl io::Write) -> io::Result<()> {
63        #[derive(Serialize)]
64        struct JsonRpc {
65            jsonrpc: &'static str,
66            #[serde(flatten)]
67            msg: Message,
68        }
69        let text = serde_json::to_string(&JsonRpc {
70            jsonrpc: "2.0",
71            msg: self,
72        })?;
73        write_msg_text(w, &text)
74    }
75}
76
77impl TryFrom<crate::Message> for Message {
78    type Error = anyhow::Error;
79
80    fn try_from(msg: crate::Message) -> anyhow::Result<Self> {
81        match msg {
82            #[cfg(feature = "lsp")]
83            crate::Message::Lsp(msg) => anyhow::bail!("unexpected LSP message: {msg:?}"),
84            crate::Message::Dap(msg) => Ok(msg),
85        }
86    }
87}
88
89impl From<Request> for crate::Message {
90    fn from(request: Request) -> crate::Message {
91        crate::Message::Dap(request.into())
92    }
93}
94
95impl From<Response> for crate::Message {
96    fn from(response: Response) -> crate::Message {
97        crate::Message::Dap(response.into())
98    }
99}
100
101impl From<Event> for crate::Message {
102    fn from(notification: Event) -> crate::Message {
103        crate::Message::Dap(notification.into())
104    }
105}
106
107impl From<Response> for LspOrDapResponse {
108    fn from(resp: Response) -> Self {
109        Self::Dap(resp)
110    }
111}
112
113impl TryFrom<LspOrDapResponse> for Response {
114    type Error = anyhow::Error;
115
116    fn try_from(resp: LspOrDapResponse) -> anyhow::Result<Self> {
117        match resp {
118            #[cfg(feature = "lsp")]
119            LspOrDapResponse::Lsp(_) => anyhow::bail!("unexpected LSP response"),
120            LspOrDapResponse::Dap(resp) => Ok(resp),
121        }
122    }
123}