1use std::{
2 fmt,
3 io::{self, BufRead, Write},
4};
5
6use serde::de::DeserializeOwned;
7use serde_derive::{Deserialize, Serialize};
8
9use crate::error::ExtractError;
10
11#[derive(Serialize, Deserialize, Debug, Clone)]
12#[serde(untagged)]
13pub enum Message {
14 Request(Request),
15 Response(Response),
16 Notification(Notification),
17}
18
19impl From<Request> for Message {
20 fn from(request: Request) -> Message {
21 Message::Request(request)
22 }
23}
24
25impl From<Response> for Message {
26 fn from(response: Response) -> Message {
27 Message::Response(response)
28 }
29}
30
31impl From<Notification> for Message {
32 fn from(notification: Notification) -> Message {
33 Message::Notification(notification)
34 }
35}
36
37#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
38#[serde(transparent)]
39pub struct RequestId(IdRepr);
40
41#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42#[serde(untagged)]
43enum IdRepr {
44 I32(i32),
45 String(String),
46}
47
48impl From<i32> for RequestId {
49 fn from(id: i32) -> RequestId {
50 RequestId(IdRepr::I32(id))
51 }
52}
53
54impl From<String> for RequestId {
55 fn from(id: String) -> RequestId {
56 RequestId(IdRepr::String(id))
57 }
58}
59
60impl fmt::Display for RequestId {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match &self.0 {
63 IdRepr::I32(it) => fmt::Display::fmt(it, f),
64 IdRepr::String(it) => fmt::Debug::fmt(it, f),
68 }
69 }
70}
71
72#[derive(Debug, Serialize, Deserialize, Clone)]
73pub struct Request {
74 pub id: RequestId,
75 pub method: String,
76 #[serde(default = "serde_json::Value::default")]
77 #[serde(skip_serializing_if = "serde_json::Value::is_null")]
78 pub params: serde_json::Value,
79}
80
81#[derive(Debug, Serialize, Deserialize, Clone)]
82pub struct Response {
83 pub id: RequestId,
87 #[serde(flatten)]
88 pub response_kind: ResponseKind,
89}
90
91#[derive(Debug, Serialize, Deserialize, Clone)]
92#[serde(untagged)]
93pub enum ResponseKind {
94 Ok { result: serde_json::Value },
95 Err { error: ResponseError },
96}
97
98#[derive(Debug, Serialize, Deserialize, Clone)]
99pub struct ResponseError {
100 pub code: i32,
101 pub message: String,
102 #[serde(skip_serializing_if = "Option::is_none", default)]
103 pub data: Option<serde_json::Value>,
104}
105
106#[derive(Clone, Copy, Debug)]
107#[non_exhaustive]
108pub enum ErrorCode {
109 ParseError = -32700,
111 InvalidRequest = -32600,
112 MethodNotFound = -32601,
113 InvalidParams = -32602,
114 InternalError = -32603,
115 ServerErrorStart = -32099,
116 ServerErrorEnd = -32000,
117
118 ServerNotInitialized = -32002,
121 UnknownErrorCode = -32001,
122
123 RequestCanceled = -32800,
127
128 ContentModified = -32801,
137
138 ServerCancelled = -32802,
144
145 RequestFailed = -32803,
152}
153
154#[derive(Debug, Serialize, Deserialize, Clone)]
155pub struct Notification {
156 pub method: String,
157 #[serde(default = "serde_json::Value::default")]
158 #[serde(skip_serializing_if = "serde_json::Value::is_null")]
159 pub params: serde_json::Value,
160}
161
162fn invalid_data(error: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
163 io::Error::new(io::ErrorKind::InvalidData, error)
164}
165
166macro_rules! invalid_data {
167 ($($tt:tt)*) => (invalid_data(format!($($tt)*)))
168}
169
170impl Message {
171 pub fn read(r: &mut impl BufRead) -> io::Result<Option<Message>> {
172 Message::_read(r)
173 }
174 fn _read(r: &mut dyn BufRead) -> io::Result<Option<Message>> {
175 let text = match read_msg_text(r)? {
176 None => return Ok(None),
177 Some(text) => text,
178 };
179
180 let msg = match serde_json::from_str(&text) {
181 Ok(msg) => msg,
182 Err(e) => {
183 return Err(invalid_data!("malformed LSP payload `{e:?}`: {text:?}"));
184 }
185 };
186
187 Ok(Some(msg))
188 }
189 pub fn write(&self, w: &mut impl Write) -> io::Result<()> {
190 self._write(w)
191 }
192 fn _write(&self, w: &mut dyn Write) -> io::Result<()> {
193 #[derive(Serialize)]
194 struct JsonRpc<'a> {
195 jsonrpc: &'static str,
196 #[serde(flatten)]
197 msg: &'a Message,
198 }
199 let text = serde_json::to_string(&JsonRpc { jsonrpc: "2.0", msg: self })?;
200 write_msg_text(w, &text)
201 }
202}
203
204impl Response {
205 pub fn new_ok<R: serde::Serialize>(id: RequestId, result: R) -> Response {
206 Response {
207 id,
208 response_kind: ResponseKind::Ok { result: serde_json::to_value(result).unwrap() },
209 }
210 }
211 pub fn new_err(id: RequestId, code: i32, message: String) -> Response {
212 let error = ResponseError { code, message, data: None };
213 Response { id, response_kind: ResponseKind::Err { error } }
214 }
215}
216
217impl Request {
218 pub fn new<P: serde::Serialize>(id: RequestId, method: String, params: P) -> Request {
219 Request { id, method, params: serde_json::to_value(params).unwrap() }
220 }
221 pub fn extract<P: DeserializeOwned>(
222 self,
223 method: &str,
224 ) -> Result<(RequestId, P), ExtractError<Request>> {
225 if self.method != method {
226 return Err(ExtractError::MethodMismatch(self));
227 }
228 match serde_json::from_value(self.params) {
229 Ok(params) => Ok((self.id, params)),
230 Err(error) => Err(ExtractError::JsonError { method: self.method, error }),
231 }
232 }
233
234 pub(crate) fn is_shutdown(&self) -> bool {
235 self.method == "shutdown"
236 }
237 pub(crate) fn is_initialize(&self) -> bool {
238 self.method == "initialize"
239 }
240}
241
242impl Notification {
243 pub fn new(method: String, params: impl serde::Serialize) -> Notification {
244 Notification { method, params: serde_json::to_value(params).unwrap() }
245 }
246 pub fn extract<P: DeserializeOwned>(
247 self,
248 method: &str,
249 ) -> Result<P, ExtractError<Notification>> {
250 if self.method != method {
251 return Err(ExtractError::MethodMismatch(self));
252 }
253 match serde_json::from_value(self.params) {
254 Ok(params) => Ok(params),
255 Err(error) => Err(ExtractError::JsonError { method: self.method, error }),
256 }
257 }
258 pub(crate) fn is_exit(&self) -> bool {
259 self.method == "exit"
260 }
261 pub(crate) fn is_initialized(&self) -> bool {
262 self.method == "initialized"
263 }
264}
265
266fn read_msg_text(inp: &mut dyn BufRead) -> io::Result<Option<String>> {
267 let mut size = None;
268 let mut buf = String::new();
269 loop {
270 buf.clear();
271 if inp.read_line(&mut buf)? == 0 {
272 return Ok(None);
273 }
274 if !buf.ends_with("\r\n") {
275 return Err(invalid_data!("malformed header: {:?}", buf));
276 }
277 let buf = &buf[..buf.len() - 2];
278 if buf.is_empty() {
279 break;
280 }
281 let mut parts = buf.splitn(2, ": ");
282 let header_name = parts.next().unwrap();
283 let header_value =
284 parts.next().ok_or_else(|| invalid_data!("malformed header: {:?}", buf))?;
285 if header_name.eq_ignore_ascii_case("Content-Length") {
286 size = Some(header_value.parse::<usize>().map_err(invalid_data)?);
287 }
288 }
289 let size: usize = size.ok_or_else(|| invalid_data!("no Content-Length"))?;
290 let mut buf = buf.into_bytes();
291 buf.resize(size, 0);
292 inp.read_exact(&mut buf)?;
293 let buf = String::from_utf8(buf).map_err(invalid_data)?;
294 log::debug!("< {buf}");
295 Ok(Some(buf))
296}
297
298fn write_msg_text(out: &mut dyn Write, msg: &str) -> io::Result<()> {
299 log::debug!("> {msg}");
300 write!(out, "Content-Length: {}\r\n\r\n", msg.len())?;
301 out.write_all(msg.as_bytes())?;
302 out.flush()?;
303 Ok(())
304}
305
306#[cfg(test)]
307mod tests {
308 use super::{Message, Notification, Request, RequestId};
309
310 #[test]
311 fn shutdown_with_explicit_null() {
312 let text = "{\"jsonrpc\": \"2.0\",\"id\": 3,\"method\": \"shutdown\", \"params\": null }";
313 let msg: Message = serde_json::from_str(text).unwrap();
314
315 assert!(
316 matches!(msg, Message::Request(req) if req.id == 3.into() && req.method == "shutdown")
317 );
318 }
319
320 #[test]
321 fn shutdown_with_no_params() {
322 let text = "{\"jsonrpc\": \"2.0\",\"id\": 3,\"method\": \"shutdown\"}";
323 let msg: Message = serde_json::from_str(text).unwrap();
324
325 assert!(
326 matches!(msg, Message::Request(req) if req.id == 3.into() && req.method == "shutdown")
327 );
328 }
329
330 #[test]
331 fn notification_with_explicit_null() {
332 let text = "{\"jsonrpc\": \"2.0\",\"method\": \"exit\", \"params\": null }";
333 let msg: Message = serde_json::from_str(text).unwrap();
334
335 assert!(matches!(msg, Message::Notification(not) if not.method == "exit"));
336 }
337
338 #[test]
339 fn notification_with_no_params() {
340 let text = "{\"jsonrpc\": \"2.0\",\"method\": \"exit\"}";
341 let msg: Message = serde_json::from_str(text).unwrap();
342
343 assert!(matches!(msg, Message::Notification(not) if not.method == "exit"));
344 }
345
346 #[test]
347 fn serialize_request_with_null_params() {
348 let msg = Message::Request(Request {
349 id: RequestId::from(3),
350 method: "shutdown".into(),
351 params: serde_json::Value::Null,
352 });
353 let serialized = serde_json::to_string(&msg).unwrap();
354
355 assert_eq!("{\"id\":3,\"method\":\"shutdown\"}", serialized);
356 }
357
358 #[test]
359 fn serialize_notification_with_null_params() {
360 let msg = Message::Notification(Notification {
361 method: "exit".into(),
362 params: serde_json::Value::Null,
363 });
364 let serialized = serde_json::to_string(&msg).unwrap();
365
366 assert_eq!("{\"method\":\"exit\"}", serialized);
367 }
368}