1use std::io;
4
5use serde::{Deserialize, Serialize};
6use serde_json::json;
7
8pub use dapts::{Event, Request, Response};
9
10use crate::{LspOrDapResponse, invalid_data_fmt, read_msg_text, write_msg_text};
11
12#[derive(Deserialize, Debug, Clone)]
14#[serde(tag = "type")]
15pub enum Message {
16 #[serde(rename = "request")]
18 Request(Request),
19 #[serde(rename = "response")]
21 Response(Response),
22 #[serde(rename = "event")]
24 Event(Event),
25 #[serde(skip)]
31 ResponseWithCommand(ResponseWithCommand),
32}
33
34#[derive(Debug, Clone)]
36pub struct ResponseWithCommand {
37 pub command: String,
39 pub response: Response,
41}
42
43impl ResponseWithCommand {
44 pub fn new(command: String, response: Response) -> Self {
46 Self { command, response }
47 }
48}
49
50impl Serialize for Message {
51 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
52 use serde::ser::Error;
53
54 let mut value = match self {
55 Message::Request(req) => serde_json::to_value(req).map_err(Error::custom)?,
56 Message::Response(resp) => serde_json::to_value(resp).map_err(Error::custom)?,
57 Message::Event(event) => serde_json::to_value(event).map_err(Error::custom)?,
58 Message::ResponseWithCommand(resp) => {
59 let mut value = serde_json::to_value(&resp.response).map_err(Error::custom)?;
60 let object = value
61 .as_object_mut()
62 .ok_or_else(|| Error::custom("DAP response did not serialize to an object"))?;
63 object.insert("command".to_owned(), json!(resp.command));
64 value
65 }
66 };
67
68 let object = value
69 .as_object_mut()
70 .ok_or_else(|| Error::custom("DAP message did not serialize to an object"))?;
71 object.insert(
72 "type".to_owned(),
73 json!(match self {
74 Message::Request(_) => "request",
75 Message::Response(_) | Message::ResponseWithCommand(_) => "response",
76 Message::Event(_) => "event",
77 }),
78 );
79
80 value.serialize(serializer)
81 }
82}
83
84impl From<Request> for Message {
85 fn from(req: Request) -> Self {
86 Message::Request(req)
87 }
88}
89
90impl From<Response> for Message {
91 fn from(resp: Response) -> Self {
92 Message::Response(resp)
93 }
94}
95
96impl From<Event> for Message {
97 fn from(event: Event) -> Self {
98 Message::Event(event)
99 }
100}
101
102impl Message {
103 pub fn read(r: &mut impl io::BufRead) -> io::Result<Option<Message>> {
105 let text = match read_msg_text(r)? {
106 None => return Ok(None),
107 Some(text) => text,
108 };
109
110 let msg = match serde_json::from_str(&text) {
111 Ok(msg) => msg,
112 Err(e) => {
113 return Err(invalid_data_fmt!("malformed DAP payload: {e:?}"));
114 }
115 };
116
117 Ok(Some(msg))
118 }
119 pub fn write(self, w: &mut impl io::Write) -> io::Result<()> {
121 #[derive(Serialize)]
122 struct JsonRpc {
123 jsonrpc: &'static str,
124 #[serde(flatten)]
125 msg: Message,
126 }
127 let text = serde_json::to_string(&JsonRpc {
128 jsonrpc: "2.0",
129 msg: self,
130 })?;
131 write_msg_text(w, &text)
132 }
133}
134
135impl TryFrom<crate::Message> for Message {
136 type Error = anyhow::Error;
137
138 fn try_from(msg: crate::Message) -> anyhow::Result<Self> {
139 match msg {
140 #[cfg(feature = "lsp")]
141 crate::Message::Lsp(msg) => anyhow::bail!("unexpected LSP message: {msg:?}"),
142 crate::Message::Dap(msg) => Ok(msg),
143 }
144 }
145}
146
147impl From<Request> for crate::Message {
148 fn from(request: Request) -> crate::Message {
149 crate::Message::Dap(request.into())
150 }
151}
152
153impl From<Response> for crate::Message {
154 fn from(response: Response) -> crate::Message {
155 crate::Message::Dap(response.into())
156 }
157}
158
159impl From<Event> for crate::Message {
160 fn from(notification: Event) -> crate::Message {
161 crate::Message::Dap(notification.into())
162 }
163}
164
165impl From<Response> for LspOrDapResponse {
166 fn from(resp: Response) -> Self {
167 Self::Dap(resp)
168 }
169}
170
171impl TryFrom<LspOrDapResponse> for Response {
172 type Error = anyhow::Error;
173
174 fn try_from(resp: LspOrDapResponse) -> anyhow::Result<Self> {
175 match resp {
176 #[cfg(feature = "lsp")]
177 LspOrDapResponse::Lsp(_) => anyhow::bail!("unexpected LSP response"),
178 LspOrDapResponse::Dap(resp) => Ok(resp),
179 }
180 }
181}