sync_ls/
dap.rs

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