1use std::{
4 fmt,
5 io::{self, BufRead, Write},
6};
7
8use serde::{Deserialize, Serialize};
9
10#[cfg(feature = "dap")]
11use crate::dap;
12#[cfg(feature = "lsp")]
13use crate::lsp;
14
15#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
17#[serde(transparent)]
18pub struct RequestId(IdRepr);
19
20impl RequestId {
21 #[cfg(feature = "dap")]
22 pub(crate) fn dap(id: RequestId) -> i64 {
23 match id.0 {
24 IdRepr::I32(it) => it as i64,
25 IdRepr::String(it) => panic!("unexpected string ID in DAP: {it}"),
26 }
27 }
28}
29
30#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
31#[serde(untagged)]
32enum IdRepr {
33 I32(i32),
34 String(String),
35}
36
37impl From<i32> for RequestId {
38 fn from(id: i32) -> RequestId {
39 RequestId(IdRepr::I32(id))
40 }
41}
42
43impl From<String> for RequestId {
44 fn from(id: String) -> RequestId {
45 RequestId(IdRepr::String(id))
46 }
47}
48
49impl fmt::Display for RequestId {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match &self.0 {
52 IdRepr::I32(it) => fmt::Display::fmt(it, f),
53 IdRepr::String(it) => fmt::Debug::fmt(it, f),
57 }
58 }
59}
60
61#[derive(Debug, Serialize, Deserialize, Clone)]
63pub struct ResponseError {
64 pub code: i32,
66 pub message: String,
68 #[serde(skip_serializing_if = "Option::is_none")]
70 pub data: Option<serde_json::Value>,
71}
72
73#[derive(Clone, Copy, Debug)]
75#[non_exhaustive]
76pub enum ErrorCode {
77 ParseError = -32700,
80 InvalidRequest = -32600,
82 MethodNotFound = -32601,
84 InvalidParams = -32602,
86 InternalError = -32603,
88 ServerErrorStart = -32099,
90 ServerErrorEnd = -32000,
92
93 ServerNotInitialized = -32002,
96 UnknownErrorCode = -32001,
99
100 RequestCanceled = -32800,
104
105 ContentModified = -32801,
114
115 ServerCancelled = -32802,
121
122 RequestFailed = -32803,
129}
130
131#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133pub enum MessageKind {
134 #[cfg(feature = "lsp")]
136 Lsp,
137 #[cfg(feature = "dap")]
139 Dap,
140}
141
142pub trait GetMessageKind {
144 fn get_message_kind() -> MessageKind;
146}
147
148#[cfg(feature = "lsp")]
149impl GetMessageKind for LspMessage {
150 fn get_message_kind() -> MessageKind {
151 MessageKind::Lsp
152 }
153}
154
155#[cfg(feature = "lsp")]
157pub type LspMessage = lsp::Message;
158#[cfg(feature = "dap")]
160pub type DapMessage = dap::Message;
161
162#[derive(Debug)]
164pub enum Message {
165 #[cfg(feature = "lsp")]
167 Lsp(LspMessage),
168 #[cfg(feature = "dap")]
170 Dap(DapMessage),
171}
172
173impl Message {
174 #[cfg(feature = "lsp")]
176 pub fn read_lsp<R: std::io::BufRead>(reader: &mut R) -> std::io::Result<Option<Self>> {
177 let msg = lsp::Message::read(reader)?;
178 Ok(msg.map(Message::Lsp))
179 }
180
181 #[cfg(feature = "dap")]
183 pub fn read_dap<R: std::io::BufRead>(reader: &mut R) -> std::io::Result<Option<Self>> {
184 let msg = dap::Message::read(reader)?;
185 Ok(msg.map(Message::Dap))
186 }
187
188 pub fn write<W: std::io::Write>(self, writer: &mut W) -> std::io::Result<()> {
190 match self {
191 #[cfg(feature = "lsp")]
192 Message::Lsp(msg) => msg.write(writer),
193 #[cfg(feature = "dap")]
194 Message::Dap(msg) => msg.write(writer),
195 }
196 }
197}
198
199pub(crate) enum LspOrDapResponse {
200 #[cfg(feature = "lsp")]
201 Lsp(lsp::Response),
202 #[cfg(feature = "dap")]
203 Dap(dap::Response),
204}
205
206pub(crate) fn read_msg_text(inp: &mut dyn BufRead) -> io::Result<Option<String>> {
207 let mut size = None;
208 let mut buf = String::new();
209 loop {
210 buf.clear();
211 if inp.read_line(&mut buf)? == 0 {
212 return Ok(None);
213 }
214 if !buf.ends_with("\r\n") {
215 return Err(invalid_data_fmt!("malformed header: {buf:?}"));
216 }
217 let buf = &buf[..buf.len() - 2];
218 if buf.is_empty() {
219 break;
220 }
221 let mut parts = buf.splitn(2, ": ");
222 let header_name = parts.next().unwrap();
223 let header_value = parts
224 .next()
225 .ok_or_else(|| invalid_data_fmt!("malformed header: {buf:?}"))?;
226 if header_name.eq_ignore_ascii_case("Content-Length") {
227 size = Some(header_value.parse::<usize>().map_err(invalid_data)?);
228 }
229 }
230 let size: usize = size.ok_or_else(|| invalid_data_fmt!("no Content-Length"))?;
231 let mut buf = buf.into_bytes();
232 buf.resize(size, 0);
233 inp.read_exact(&mut buf)?;
234 let buf = String::from_utf8(buf).map_err(invalid_data)?;
235 log::debug!("< {}", buf);
236 Ok(Some(buf))
237}
238
239pub(crate) fn write_msg_text(out: &mut dyn Write, msg: &str) -> io::Result<()> {
240 log::debug!("> {}", msg);
241 write!(out, "Content-Length: {}\r\n\r\n", msg.len())?;
242 out.write_all(msg.as_bytes())?;
243 out.flush()?;
244 Ok(())
245}
246
247pub(crate) fn invalid_data(
248 error: impl Into<Box<dyn std::error::Error + Send + Sync>>,
249) -> io::Error {
250 io::Error::new(io::ErrorKind::InvalidData, error)
251}
252
253macro_rules! invalid_data_fmt {
254 ($($tt:tt)*) => ($crate::invalid_data(format!($($tt)*)))
255}
256pub(crate) use invalid_data_fmt;