1pub use self::error::{Error, ErrorCode};
4pub use self::router::{FromParams, IntoResponse, Method};
5
6pub(crate) use self::router::Router;
7
8use std::borrow::Cow;
9use std::fmt::{self, Debug, Display, Formatter};
10
11use lsp_types::NumberOrString;
12use serde::de::{self, Deserializer};
13use serde::ser::Serializer;
14use serde::{Deserialize, Serialize};
15use serde_json::Value;
16
17mod error;
18mod router;
19
20pub type Result<T> = std::result::Result<T, Error>;
24
25#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
27#[serde(untagged)]
28#[derive(Default)]
29pub enum Id {
30 Number(i64),
32 String(String),
34 #[default]
40 Null,
41}
42
43impl Display for Id {
44 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
45 match self {
46 Id::Number(id) => Display::fmt(id, f),
47 Id::String(id) => Debug::fmt(id, f),
48 Id::Null => f.write_str("null"),
49 }
50 }
51}
52
53impl From<i64> for Id {
54 fn from(n: i64) -> Self {
55 Id::Number(n)
56 }
57}
58
59impl From<&'_ str> for Id {
60 fn from(s: &'_ str) -> Self {
61 Id::String(s.to_string())
62 }
63}
64
65impl From<String> for Id {
66 fn from(s: String) -> Self {
67 Id::String(s)
68 }
69}
70
71impl From<NumberOrString> for Id {
72 fn from(num_or_str: NumberOrString) -> Self {
73 match num_or_str {
74 NumberOrString::Number(num) => Id::Number(num as i64),
75 NumberOrString::String(s) => Id::String(s),
76 }
77 }
78}
79
80fn deserialize_some<'de, T, D>(deserializer: D) -> std::result::Result<Option<T>, D::Error>
81where
82 T: Deserialize<'de>,
83 D: Deserializer<'de>,
84{
85 T::deserialize(deserializer).map(Some)
86}
87
88#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
90pub struct Request {
91 jsonrpc: Version,
92 #[serde(default)]
93 method: Cow<'static, str>,
94 #[serde(default, deserialize_with = "deserialize_some")]
95 #[serde(skip_serializing_if = "Option::is_none")]
96 params: Option<Value>,
97 #[serde(default, deserialize_with = "deserialize_some")]
98 #[serde(skip_serializing_if = "Option::is_none")]
99 id: Option<Id>,
100}
101
102impl Request {
103 pub fn build<M>(method: M) -> RequestBuilder
107 where
108 M: Into<Cow<'static, str>>,
109 {
110 RequestBuilder {
111 method: method.into(),
112 params: None,
113 id: None,
114 }
115 }
116
117 pub(crate) fn from_request<R>(id: Id, params: R::Params) -> Self
119 where
120 R: lsp_types::request::Request,
121 {
122 Request {
125 jsonrpc: Version,
126 method: R::METHOD.into(),
127 params: Some(serde_json::to_value(params).unwrap()),
128 id: Some(id),
129 }
130 }
131
132 pub(crate) fn from_notification<N>(params: N::Params) -> Self
134 where
135 N: lsp_types::notification::Notification,
136 {
137 Request {
140 jsonrpc: Version,
141 method: N::METHOD.into(),
142 params: Some(serde_json::to_value(params).unwrap()),
143 id: None,
144 }
145 }
146
147 #[inline]
149 pub fn method(&self) -> &str {
150 self.method.as_ref()
151 }
152
153 #[inline]
155 pub fn id(&self) -> Option<&Id> {
156 self.id.as_ref()
157 }
158
159 #[inline]
161 pub fn params(&self) -> Option<&Value> {
162 self.params.as_ref()
163 }
164
165 #[inline]
167 pub fn into_parts(self) -> (Cow<'static, str>, Option<Id>, Option<Value>) {
168 (self.method, self.id, self.params)
169 }
170}
171
172impl Display for Request {
173 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
174 let mut w = WriterFormatter { inner: f };
175 serde_json::to_writer(&mut w, self).map_err(|_| fmt::Error)
176 }
177}
178
179struct WriterFormatter<'a, 'b: 'a> {
180 inner: &'a mut Formatter<'b>,
181}
182
183impl<'a, 'b> std::io::Write for WriterFormatter<'a, 'b> {
184 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
185 fn io_error<E>(_: E) -> std::io::Error {
186 std::io::Error::new(std::io::ErrorKind::Other, "fmt error")
189 }
190 let s = std::str::from_utf8(buf).map_err(io_error)?;
191 self.inner.write_str(s).map_err(io_error)?;
192 Ok(buf.len())
193 }
194
195 fn flush(&mut self) -> std::io::Result<()> {
196 Ok(())
197 }
198}
199
200#[derive(Debug)]
204pub struct RequestBuilder {
205 method: Cow<'static, str>,
206 params: Option<Value>,
207 id: Option<Id>,
208}
209
210impl RequestBuilder {
211 pub fn id<I: Into<Id>>(mut self, id: I) -> Self {
215 self.id = Some(id.into());
216 self
217 }
218
219 pub fn params<V: Into<Value>>(mut self, params: V) -> Self {
223 self.params = Some(params.into());
224 self
225 }
226
227 pub fn finish(self) -> Request {
229 Request {
230 jsonrpc: Version,
231 method: self.method,
232 params: self.params,
233 id: self.id,
234 }
235 }
236}
237
238#[derive(Clone, PartialEq, Deserialize, Serialize)]
240pub struct Response {
241 jsonrpc: Version,
242 #[serde(flatten)]
243 kind: ResponseKind,
244 id: Id,
245}
246
247impl Response {
248 #[inline]
250 pub const fn from_ok(id: Id, result: Value) -> Self {
251 Response {
252 jsonrpc: Version,
253 kind: ResponseKind::Ok { result },
254 id,
255 }
256 }
257
258 #[inline]
260 pub const fn from_error(id: Id, error: Error) -> Self {
261 Response {
262 jsonrpc: Version,
263 kind: ResponseKind::Err { error },
264 id,
265 }
266 }
267
268 pub fn from_parts(id: Id, body: Result<Value>) -> Self {
270 match body {
271 Ok(result) => Response::from_ok(id, result),
272 Err(error) => Response::from_error(id, error),
273 }
274 }
275
276 pub fn into_parts(self) -> (Id, Result<Value>) {
279 match self.kind {
280 ResponseKind::Ok { result } => (self.id, Ok(result)),
281 ResponseKind::Err { error } => (self.id, Err(error)),
282 }
283 }
284
285 #[inline]
287 pub const fn is_ok(&self) -> bool {
288 matches!(self.kind, ResponseKind::Ok { .. })
289 }
290
291 #[inline]
293 pub const fn is_error(&self) -> bool {
294 !self.is_ok()
295 }
296
297 #[inline]
301 pub const fn result(&self) -> Option<&Value> {
302 match &self.kind {
303 ResponseKind::Ok { result } => Some(result),
304 _ => None,
305 }
306 }
307
308 #[inline]
312 pub const fn error(&self) -> Option<&Error> {
313 match &self.kind {
314 ResponseKind::Err { error } => Some(error),
315 _ => None,
316 }
317 }
318
319 #[inline]
321 pub const fn id(&self) -> &Id {
322 &self.id
323 }
324}
325
326impl Debug for Response {
327 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
328 let mut d = f.debug_struct("Response");
329 d.field("jsonrpc", &self.jsonrpc);
330
331 match &self.kind {
332 ResponseKind::Ok { result } => d.field("result", result),
333 ResponseKind::Err { error } => d.field("error", error),
334 };
335
336 d.field("id", &self.id).finish()
337 }
338}
339
340#[derive(Clone, PartialEq, Deserialize, Serialize)]
341#[serde(untagged)]
342enum ResponseKind {
343 Ok { result: Value },
344 Err { error: Error },
345}
346
347#[derive(Deserialize, Serialize)]
349#[cfg_attr(test, derive(Debug, PartialEq))]
350#[serde(untagged)]
351pub(crate) enum Message {
352 Response(Response),
354 Request(Request),
356}
357
358#[derive(Clone, Copy, Debug, PartialEq)]
359pub(crate) struct Version;
360
361impl<'de> Deserialize<'de> for Version {
362 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
363 where
364 D: Deserializer<'de>,
365 {
366 match Cow::<'de, str>::deserialize(deserializer)?.as_ref() {
367 "2.0" => Ok(Version),
368 _ => Err(de::Error::custom("expected JSON-RPC version \"2.0\"")),
369 }
370 }
371}
372
373impl Serialize for Version {
374 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
375 where
376 S: Serializer,
377 {
378 "2.0".serialize(serializer)
379 }
380}
381
382pub(crate) fn not_initialized_error() -> Error {
387 Error {
388 code: ErrorCode::ServerError(-32002),
389 message: "Server not initialized".to_string(),
390 data: None,
391 }
392}
393
394#[cfg(test)]
395mod tests {
396 use serde_json::json;
397
398 use super::*;
399
400 #[test]
401 fn incoming_from_str_or_value() {
402 let v = json!({"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":0});
403 let from_str: Message = serde_json::from_str(&v.to_string()).unwrap();
404 let from_value: Message = serde_json::from_value(v).unwrap();
405 assert_eq!(from_str, from_value);
406 }
407
408 #[test]
409 fn outgoing_from_str_or_value() {
410 let v = json!({"jsonrpc":"2.0","result":{},"id":1});
411 let from_str: Message = serde_json::from_str(&v.to_string()).unwrap();
412 let from_value: Message = serde_json::from_value(v).unwrap();
413 assert_eq!(from_str, from_value);
414 }
415
416 #[test]
417 fn parses_incoming_message() {
418 let server_request =
419 json!({"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":0});
420 let incoming = serde_json::from_value(server_request).unwrap();
421 assert!(matches!(incoming, Message::Request(_)));
422
423 let server_notif = json!({"jsonrpc":"2.0","method":"initialized","params":{}});
424 let incoming = serde_json::from_value(server_notif).unwrap();
425 assert!(matches!(incoming, Message::Request(_)));
426
427 let client_request = json!({"jsonrpc":"2.0","id":0,"result":[null]});
428 let incoming = serde_json::from_value(client_request).unwrap();
429 assert!(matches!(incoming, Message::Response(_)));
430 }
431
432 #[test]
433 fn parses_outgoing_message() {
434 let client_request = json!({"jsonrpc":"2.0","method":"workspace/configuration","params":{"scopeUri":null,"section":"foo"},"id":0});
435 let outgoing = serde_json::from_value(client_request).unwrap();
436 assert!(matches!(outgoing, Message::Request(_)));
437
438 let client_notif = json!({"jsonrpc":"2.0","method":"window/logMessage","params":{"message":"foo","type":0}});
439 let outgoing = serde_json::from_value(client_notif).unwrap();
440 assert!(matches!(outgoing, Message::Request(_)));
441
442 let server_response = json!({"jsonrpc":"2.0","id":0,"result":[null]});
443 let outgoing = serde_json::from_value(server_response).unwrap();
444 assert!(matches!(outgoing, Message::Response(_)));
445 }
446
447 #[test]
448 fn parses_invalid_server_request() {
449 let unknown_method = json!({"jsonrpc":"2.0","method":"foo"});
450 let incoming = serde_json::from_value(unknown_method).unwrap();
451 assert!(matches!(incoming, Message::Request(_)));
452
453 let unknown_method_with_id = json!({"jsonrpc":"2.0","method":"foo","id":0});
454 let incoming = serde_json::from_value(unknown_method_with_id).unwrap();
455 assert!(matches!(incoming, Message::Request(_)));
456
457 let missing_method = json!({"jsonrpc":"2.0"});
458 let incoming = serde_json::from_value(missing_method).unwrap();
459 assert!(matches!(incoming, Message::Request(_)));
460
461 let missing_method_with_id = json!({"jsonrpc":"2.0","id":0});
462 let incoming = serde_json::from_value(missing_method_with_id).unwrap();
463 assert!(matches!(incoming, Message::Request(_)));
464 }
465
466 #[test]
467 fn accepts_null_request_id() {
468 let request_id: Id = serde_json::from_value(json!(null)).unwrap();
469 assert_eq!(request_id, Id::Null);
470 }
471
472 #[test]
473 fn accepts_negative_integer_request_id() {
474 let request_id: Id = serde_json::from_value(json!(-1)).unwrap();
475 assert_eq!(request_id, Id::Number(-1));
476 }
477}