tower_lsp/
jsonrpc.rs
1pub(crate) use self::error::not_initialized_error;
4pub use self::error::{Error, ErrorCode, Result};
5pub use self::request::{Request, RequestBuilder};
6pub use self::response::Response;
7pub(crate) use self::router::Router;
8pub use self::router::{FromParams, IntoResponse, Method};
9
10use std::borrow::Cow;
11use std::fmt::{self, Debug, Display, Formatter};
12
13use lsp_types::NumberOrString;
14use serde::de::{self, Deserializer};
15use serde::ser::Serializer;
16use serde::{Deserialize, Serialize};
17
18mod error;
19mod request;
20mod response;
21mod router;
22
23#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
25#[serde(untagged)]
26pub enum Id {
27 Number(i64),
29 String(String),
31 Null,
37}
38
39impl Default for Id {
40 fn default() -> Self {
41 Id::Null
42 }
43}
44
45impl Display for Id {
46 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
47 match self {
48 Id::Number(id) => Display::fmt(id, f),
49 Id::String(id) => Debug::fmt(id, f),
50 Id::Null => f.write_str("null"),
51 }
52 }
53}
54
55impl From<i64> for Id {
56 fn from(n: i64) -> Self {
57 Id::Number(n)
58 }
59}
60
61impl From<&'_ str> for Id {
62 fn from(s: &'_ str) -> Self {
63 Id::String(s.to_string())
64 }
65}
66
67impl From<String> for Id {
68 fn from(s: String) -> Self {
69 Id::String(s)
70 }
71}
72
73impl From<NumberOrString> for Id {
74 fn from(num_or_str: NumberOrString) -> Self {
75 match num_or_str {
76 NumberOrString::Number(num) => Id::Number(num as i64),
77 NumberOrString::String(s) => Id::String(s),
78 }
79 }
80}
81
82#[derive(Clone, Debug, PartialEq)]
83struct Version;
84
85impl<'de> Deserialize<'de> for Version {
86 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
87 where
88 D: Deserializer<'de>,
89 {
90 #[derive(Deserialize)]
91 struct Inner<'a>(#[serde(borrow)] Cow<'a, str>);
92
93 let Inner(ver) = Inner::deserialize(deserializer)?;
94
95 match ver.as_ref() {
96 "2.0" => Ok(Version),
97 _ => Err(de::Error::custom("expected JSON-RPC version \"2.0\"")),
98 }
99 }
100}
101
102impl Serialize for Version {
103 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
104 where
105 S: Serializer,
106 {
107 serializer.serialize_str("2.0")
108 }
109}
110
111#[derive(Deserialize, Serialize)]
113#[cfg_attr(test, derive(Debug, PartialEq))]
114#[serde(untagged)]
115pub(crate) enum Message {
116 Response(Response),
118 Request(Request),
120}
121
122#[cfg(test)]
123mod tests {
124 use serde_json::json;
125
126 use super::*;
127
128 #[test]
129 fn incoming_from_str_or_value() {
130 let v = json!({"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":0});
131 let from_str: Message = serde_json::from_str(&v.to_string()).unwrap();
132 let from_value: Message = serde_json::from_value(v).unwrap();
133 assert_eq!(from_str, from_value);
134 }
135
136 #[test]
137 fn outgoing_from_str_or_value() {
138 let v = json!({"jsonrpc":"2.0","result":{},"id":1});
139 let from_str: Message = serde_json::from_str(&v.to_string()).unwrap();
140 let from_value: Message = serde_json::from_value(v).unwrap();
141 assert_eq!(from_str, from_value);
142 }
143
144 #[test]
145 fn parses_incoming_message() {
146 let server_request =
147 json!({"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":0});
148 let incoming = serde_json::from_value(server_request).unwrap();
149 assert!(matches!(incoming, Message::Request(_)));
150
151 let server_notif = json!({"jsonrpc":"2.0","method":"initialized","params":{}});
152 let incoming = serde_json::from_value(server_notif).unwrap();
153 assert!(matches!(incoming, Message::Request(_)));
154
155 let client_request = json!({"jsonrpc":"2.0","id":0,"result":[null]});
156 let incoming = serde_json::from_value(client_request).unwrap();
157 assert!(matches!(incoming, Message::Response(_)));
158 }
159
160 #[test]
161 fn parses_outgoing_message() {
162 let client_request = json!({"jsonrpc":"2.0","method":"workspace/configuration","params":{"scopeUri":null,"section":"foo"},"id":0});
163 let outgoing = serde_json::from_value(client_request).unwrap();
164 assert!(matches!(outgoing, Message::Request(_)));
165
166 let client_notif = json!({"jsonrpc":"2.0","method":"window/logMessage","params":{"message":"foo","type":0}});
167 let outgoing = serde_json::from_value(client_notif).unwrap();
168 assert!(matches!(outgoing, Message::Request(_)));
169
170 let server_response = json!({"jsonrpc":"2.0","id":0,"result":[null]});
171 let outgoing = serde_json::from_value(server_response).unwrap();
172 assert!(matches!(outgoing, Message::Response(_)));
173 }
174
175 #[test]
176 fn parses_invalid_server_request() {
177 let unknown_method = json!({"jsonrpc":"2.0","method":"foo"});
178 let incoming = serde_json::from_value(unknown_method).unwrap();
179 assert!(matches!(incoming, Message::Request(_)));
180
181 let unknown_method_with_id = json!({"jsonrpc":"2.0","method":"foo","id":0});
182 let incoming = serde_json::from_value(unknown_method_with_id).unwrap();
183 assert!(matches!(incoming, Message::Request(_)));
184
185 let missing_method = json!({"jsonrpc":"2.0"});
186 let incoming = serde_json::from_value(missing_method).unwrap();
187 assert!(matches!(incoming, Message::Request(_)));
188
189 let missing_method_with_id = json!({"jsonrpc":"2.0","id":0});
190 let incoming = serde_json::from_value(missing_method_with_id).unwrap();
191 assert!(matches!(incoming, Message::Request(_)));
192 }
193
194 #[test]
195 fn accepts_null_request_id() {
196 let request_id: Id = serde_json::from_value(json!(null)).unwrap();
197 assert_eq!(request_id, Id::Null);
198 }
199
200 #[test]
201 fn accepts_negative_integer_request_id() {
202 let request_id: Id = serde_json::from_value(json!(-1)).unwrap();
203 assert_eq!(request_id, Id::Number(-1));
204 }
205}