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, with = "ResponseResult")]
88 pub response_result: Result<serde_json::Value, ResponseError>,
89}
90
91#[derive(Serialize, Deserialize)]
92#[serde(remote = "Result<serde_json::Value, ResponseError>")]
93enum ResponseResult {
94 #[serde(rename = "result")]
95 Ok(serde_json::Value),
96 #[serde(rename = "error")]
97 Err(ResponseError),
98}
99
100#[derive(Debug, Serialize, Deserialize, Clone)]
101pub struct ResponseError {
102 pub code: i32,
103 pub message: String,
104 #[serde(skip_serializing_if = "Option::is_none", default)]
105 pub data: Option<serde_json::Value>,
106}
107
108#[derive(Clone, Copy, Debug)]
109#[non_exhaustive]
110pub enum ErrorCode {
111 ParseError = -32700,
113 InvalidRequest = -32600,
114 MethodNotFound = -32601,
115 InvalidParams = -32602,
116 InternalError = -32603,
117 ServerErrorStart = -32099,
118 ServerErrorEnd = -32000,
119
120 ServerNotInitialized = -32002,
123 UnknownErrorCode = -32001,
124
125 RequestCanceled = -32800,
129
130 ContentModified = -32801,
139
140 ServerCancelled = -32802,
146
147 RequestFailed = -32803,
154}
155
156#[derive(Debug, Serialize, Deserialize, Clone)]
157pub struct Notification {
158 pub method: String,
159 #[serde(default = "serde_json::Value::default")]
160 #[serde(skip_serializing_if = "serde_json::Value::is_null")]
161 pub params: serde_json::Value,
162}
163
164fn invalid_data(error: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
165 io::Error::new(io::ErrorKind::InvalidData, error)
166}
167
168macro_rules! invalid_data {
169 ($($tt:tt)*) => (invalid_data(format!($($tt)*)))
170}
171
172impl Message {
173 pub fn read(r: &mut impl BufRead) -> io::Result<Option<Message>> {
174 Message::_read(r)
175 }
176 fn _read(r: &mut dyn BufRead) -> io::Result<Option<Message>> {
177 let text = match read_msg_text(r)? {
178 None => return Ok(None),
179 Some(text) => text,
180 };
181
182 let msg = match serde_json::from_str(&text) {
183 Ok(msg) => msg,
184 Err(e) => {
185 return Err(invalid_data!("malformed LSP payload `{e:?}`: {text:?}"));
186 }
187 };
188
189 Ok(Some(msg))
190 }
191 pub fn write(&self, w: &mut impl Write) -> io::Result<()> {
192 self._write(w)
193 }
194 fn _write(&self, w: &mut dyn Write) -> io::Result<()> {
195 #[derive(Serialize)]
196 struct JsonRpc<'a> {
197 jsonrpc: &'static str,
198 #[serde(flatten)]
199 msg: &'a Message,
200 }
201 let text = serde_json::to_string(&JsonRpc { jsonrpc: "2.0", msg: self })?;
202 write_msg_text(w, &text)
203 }
204}
205
206impl Response {
207 pub fn new_ok<R: serde::Serialize>(id: RequestId, result: R) -> Response {
208 Response { id, response_result: Ok(serde_json::to_value(result).unwrap()) }
209 }
210 pub fn new_err(id: RequestId, code: i32, message: String) -> Response {
211 let error = ResponseError { code, message, data: None };
212 Response { id, response_result: Err(error) }
213 }
214}
215
216impl Request {
217 pub fn new<P: serde::Serialize>(id: RequestId, method: String, params: P) -> Request {
218 Request { id, method, params: serde_json::to_value(params).unwrap() }
219 }
220 pub fn extract<P: DeserializeOwned>(
221 self,
222 method: &str,
223 ) -> Result<(RequestId, P), ExtractError<Request>> {
224 if self.method != method {
225 return Err(ExtractError::MethodMismatch(self));
226 }
227 match serde_json::from_value(self.params) {
228 Ok(params) => Ok((self.id, params)),
229 Err(error) => Err(ExtractError::JsonError { method: self.method, error }),
230 }
231 }
232
233 pub(crate) fn is_shutdown(&self) -> bool {
234 self.method == "shutdown"
235 }
236 pub(crate) fn is_initialize(&self) -> bool {
237 self.method == "initialize"
238 }
239}
240
241impl Notification {
242 pub fn new(method: String, params: impl serde::Serialize) -> Notification {
243 Notification { method, params: serde_json::to_value(params).unwrap() }
244 }
245 pub fn extract<P: DeserializeOwned>(
246 self,
247 method: &str,
248 ) -> Result<P, ExtractError<Notification>> {
249 if self.method != method {
250 return Err(ExtractError::MethodMismatch(self));
251 }
252 match serde_json::from_value(self.params) {
253 Ok(params) => Ok(params),
254 Err(error) => Err(ExtractError::JsonError { method: self.method, error }),
255 }
256 }
257 pub(crate) fn is_exit(&self) -> bool {
258 self.method == "exit"
259 }
260 pub(crate) fn is_initialized(&self) -> bool {
261 self.method == "initialized"
262 }
263}
264
265fn read_msg_text(inp: &mut dyn BufRead) -> io::Result<Option<String>> {
266 let mut size = None;
267 let mut buf = String::new();
268 loop {
269 buf.clear();
270 if inp.read_line(&mut buf)? == 0 {
271 return Ok(None);
272 }
273 if !buf.ends_with("\r\n") {
274 return Err(invalid_data!("malformed header: {:?}", buf));
275 }
276 let buf = &buf[..buf.len() - 2];
277 if buf.is_empty() {
278 break;
279 }
280 let mut parts = buf.splitn(2, ": ");
281 let header_name = parts.next().unwrap();
282 let header_value =
283 parts.next().ok_or_else(|| invalid_data!("malformed header: {:?}", buf))?;
284 if header_name.eq_ignore_ascii_case("Content-Length") {
285 size = Some(header_value.parse::<usize>().map_err(invalid_data)?);
286 }
287 }
288 let size: usize = size.ok_or_else(|| invalid_data!("no Content-Length"))?;
289 let mut buf = buf.into_bytes();
290 buf.resize(size, 0);
291 inp.read_exact(&mut buf)?;
292 let buf = String::from_utf8(buf).map_err(invalid_data)?;
293 log::debug!("< {buf}");
294 Ok(Some(buf))
295}
296
297fn write_msg_text(out: &mut dyn Write, msg: &str) -> io::Result<()> {
298 log::debug!("> {msg}");
299 write!(out, "Content-Length: {}\r\n\r\n", msg.len())?;
300 out.write_all(msg.as_bytes())?;
301 out.flush()?;
302 Ok(())
303}
304
305#[cfg(test)]
306mod tests {
307 use super::{Message, Notification, Request, RequestId, Response};
308
309 #[test]
310 fn shutdown_with_explicit_null() {
311 let text = r#"{"jsonrpc": "2.0","id": 3,"method": "shutdown", "params": null }"#;
312 let msg: Message = serde_json::from_str(text).unwrap();
313
314 assert!(
315 matches!(msg, Message::Request(req) if req.id == 3.into() && req.method == "shutdown")
316 );
317 }
318
319 #[test]
320 fn shutdown_with_no_params() {
321 let text = r#"{"jsonrpc": "2.0","id": 3,"method": "shutdown"}"#;
322 let msg: Message = serde_json::from_str(text).unwrap();
323
324 assert!(
325 matches!(msg, Message::Request(req) if req.id == 3.into() && req.method == "shutdown")
326 );
327 }
328
329 #[test]
330 fn notification_with_explicit_null() {
331 let text = r#"{"jsonrpc": "2.0","method": "exit", "params": null }"#;
332 let msg: Message = serde_json::from_str(text).unwrap();
333
334 assert!(matches!(msg, Message::Notification(not) if not.method == "exit"));
335 }
336
337 #[test]
338 fn notification_with_no_params() {
339 let text = r#"{"jsonrpc": "2.0","method": "exit"}"#;
340 let msg: Message = serde_json::from_str(text).unwrap();
341
342 assert!(matches!(msg, Message::Notification(not) if not.method == "exit"));
343 }
344
345 #[test]
346 fn serialize_request_with_null_params() {
347 let msg = Message::Request(Request {
348 id: RequestId::from(3),
349 method: "shutdown".into(),
350 params: serde_json::Value::Null,
351 });
352 let serialized = serde_json::to_string(&msg).unwrap();
353
354 assert_eq!(r#"{"id":3,"method":"shutdown"}"#, serialized);
355 }
356
357 #[test]
358 fn serialize_notification_with_null_params() {
359 let msg = Message::Notification(Notification {
360 method: "exit".into(),
361 params: serde_json::Value::Null,
362 });
363 let serialized = serde_json::to_string(&msg).unwrap();
364
365 assert_eq!(r#"{"method":"exit"}"#, serialized);
366 }
367
368 #[test]
369 fn serialize_ok_response() {
370 let msg = Message::Response(Response::new_ok(RequestId::from(3), "success"));
371 let serialized = serde_json::to_string(&msg).unwrap();
372
373 assert_eq!(r#"{"id":3,"result":"success"}"#, serialized);
374 }
375
376 #[test]
377 fn serialize_err_response() {
378 let msg = Message::Response(Response::new_err(
379 RequestId::from(3),
380 -32600,
381 String::from("bad response message"),
382 ));
383 let serialized = serde_json::to_string(&msg).unwrap();
384
385 assert_eq!(
386 r#"{"id":3,"error":{"code":-32600,"message":"bad response message"}}"#,
387 serialized
388 );
389 }
390}