Skip to main content

gen_lsp_types/
json_rpc.rs

1use serde::{Deserialize, Deserializer, Serialize};
2use serde_json::Value;
3
4use crate::{ErrorCodes, Notification, Request};
5
6pub(crate) fn deserialize_some<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
7where
8    T: Deserialize<'de>,
9    D: Deserializer<'de>,
10{
11    T::deserialize(deserializer).map(Some)
12}
13
14#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
15enum Version {
16    #[serde(rename = "2.0")]
17    TwoPointZero,
18}
19
20/// A unique ID used to correlate requests and responses together.
21#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
22#[serde(untagged)]
23pub enum Id {
24    /// Numeric ID.
25    Number(i64),
26    /// String ID.
27    String(String),
28    /// Null ID.
29    ///
30    /// The use of Null as a value for the id member in a Request object is discouraged, because
31    /// this specification uses a value of Null for Responses with an unknown id. Also, because
32    /// JSON-RPC 1.0 uses an id value of Null for Notifications this could cause confusion in
33    /// handling.
34    Null,
35}
36
37impl From<i64> for Id {
38    fn from(value: i64) -> Self {
39        Self::Number(value)
40    }
41}
42
43impl From<i32> for Id {
44    fn from(value: i32) -> Self {
45        Self::Number(value as i64)
46    }
47}
48
49impl From<String> for Id {
50    fn from(value: String) -> Self {
51        Self::String(value)
52    }
53}
54
55impl From<()> for Id {
56    fn from((): ()) -> Self {
57        Self::Null
58    }
59}
60
61impl From<crate::Id> for Id {
62    fn from(value: crate::Id) -> Self {
63        match value {
64            crate::Id::Int(int) => Self::Number(int as i64),
65            crate::Id::String(string) => Self::String(string),
66        }
67    }
68}
69
70impl TryFrom<Id> for crate::Id {
71    type Error = String;
72
73    fn try_from(value: Id) -> Result<Self, Self::Error> {
74        match value {
75            Id::String(string) => Ok(Self::String(string)),
76            Id::Number(number) => Ok(Self::Int(
77                i32::try_from(number).map_err(|e| format!("Request ID int too big: {e}"))?,
78            )),
79            Id::Null => Err(Self::Error::from("Id cannot be null")),
80        }
81    }
82}
83
84/// A JSON-RPC Request (or Notification) object.
85#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Eq)]
86pub struct RequestObject {
87    /// A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
88    jsonrpc: Version,
89    /// An identifier established by the Client that MUST contain a String, Number, or NULL value if
90    /// included. If it is not included it is assumed to be a notification. The value SHOULD
91    /// normally not be Null and Numbers SHOULD NOT contain fractional parts.
92    #[serde(default, deserialize_with = "deserialize_some")]
93    #[serde(skip_serializing_if = "Option::is_none")]
94    id: Option<Id>,
95    /// A String containing the name of the method to be invoked. Method names that begin with the
96    /// word rpc followed by a period character (U+002E or ASCII 46) are reserved for rpc-internal
97    /// methods and extensions and MUST NOT be used for anything else.
98    #[serde(default)]
99    method: String,
100    /// A Structured value that holds the parameter values to be used during the invocation of the
101    /// method. This member MAY be omitted.
102    ///
103    /// If present, parameters for the rpc call MUST be provided as a Structured value. Either
104    /// by-position through an Array or by-name through an Object.
105    #[serde(default, deserialize_with = "deserialize_some")]
106    #[serde(skip_serializing_if = "Option::is_none")]
107    params: Option<Value>,
108}
109
110impl RequestObject {
111    /// Creates a JSON-RPC Request object from a server request.
112    ///
113    /// # Panics
114    ///
115    /// Will panic if `result` cannot be serialized (impossible unless the trait was implemented
116    /// incorrectly).
117    pub fn from_request<R>(id: Id, params: R::Params) -> Self
118    where
119        R: Request,
120    {
121        let params = serde_json::to_value(params).expect("Invalid request params");
122        let params = match params {
123            Value::Null => None,
124            Value::Array(_) | Value::Object(_) => Some(params),
125            _ => panic!("Parameters must be an object or array, if not omitted."),
126        };
127        Self {
128            jsonrpc: Version::TwoPointZero,
129            id: Some(id),
130            params,
131            method: R::METHOD.into(),
132        }
133    }
134
135    /// Creates a JSON-RPC Request object from a server notification.
136    ///
137    /// # Panics
138    ///
139    /// Will panic if `result` cannot be serialized (impossible unless the trait was implemented
140    /// incorrectly).
141    pub fn from_notification<N>(params: N::Params) -> Self
142    where
143        N: Notification,
144    {
145        let params = serde_json::to_value(params).expect("Invalid request params");
146        let params = match params {
147            Value::Null => None,
148            Value::Array(_) | Value::Object(_) => Some(params),
149            _ => panic!("Parameters must be an object or array, if not omitted."),
150        };
151        Self {
152            jsonrpc: Version::TwoPointZero,
153            method: N::METHOD.to_string(),
154            params,
155            id: None,
156        }
157    }
158
159    /// Returns the method to be invoked.
160    #[must_use]
161    pub fn method(&self) -> &str {
162        self.method.as_ref()
163    }
164
165    /// Returns the id.
166    #[must_use]
167    pub const fn id(&self) -> Option<&Id> {
168        self.id.as_ref()
169    }
170
171    /// Returns the params.
172    #[must_use]
173    pub const fn params(&self) -> Option<&Value> {
174        self.params.as_ref()
175    }
176
177    /// Splits the request into the method name, request ID, and the parameters.
178    #[must_use]
179    pub fn into_parts(self) -> (String, Option<Id>, Option<Value>) {
180        (self.method, self.id, self.params)
181    }
182}
183
184#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
185#[serde(untagged)]
186enum Kind {
187    /// This member is REQUIRED on success. This member MUST NOT exist if there was an error
188    /// invoking the method. The value of this member is determined by the method invoked on the
189    /// Server.
190    Ok { result: Value },
191    /// This member is REQUIRED on error. This member MUST NOT exist if there was no error triggered
192    /// during invocation. The value for this member MUST be an Object as defined in section 5.1.
193    Err { error: Error },
194}
195
196/// A JSON-RPC Error object.
197#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
198pub struct Error {
199    /// A Number that indicates the error type that occurred.
200    pub code: ErrorCodes,
201    /// A String providing a short description of the error. The message SHOULD be limited to a
202    /// concise single sentence.
203    pub message: String,
204    /// A Primitive or Structured value that contains additional information about the error. This
205    /// may be omitted. The value of this member is defined by the Server (e.g. detailed error
206    /// information, nested errors etc.).
207    #[serde(skip_serializing_if = "Option::is_none")]
208    pub data: Option<Value>,
209}
210
211/// A JSON-RPC Response object.
212#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
213pub struct ResponseObject {
214    /// A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
215    jsonrpc: Version,
216    #[serde(flatten)]
217    kind: Kind,
218    /// This member is REQUIRED. It MUST be the same as the value of the id member in the
219    /// Request Object. If there was an error in detecting the id in the Request object
220    /// (e.g. Parse error/Invalid Request), it MUST be Null.
221    id: Id,
222}
223
224impl ResponseObject {
225    /// Creates a successful Response object from a result value.
226    ///
227    /// # Panics
228    ///
229    /// Will panic if `result` cannot be serialized (impossible unless the trait was implemented
230    /// incorrectly).
231    pub fn from_success<R>(id: Id, result: R::Result) -> Self
232    where
233        R: Request,
234    {
235        let result = serde_json::to_value(result).unwrap();
236        Self {
237            jsonrpc: Version::TwoPointZero,
238            kind: Kind::Ok { result },
239            id,
240        }
241    }
242
243    /// Creates an error Response object from an error value.
244    #[must_use]
245    pub const fn from_error(id: Id, error: Error) -> Self {
246        Self {
247            jsonrpc: Version::TwoPointZero,
248            kind: Kind::Err { error },
249            id,
250        }
251    }
252
253    /// Returns `true` if the Response object indicates success.
254    #[must_use]
255    pub const fn is_ok(&self) -> bool {
256        matches!(self.kind, Kind::Ok { .. })
257    }
258
259    /// Returns `true` if the Response object indicates failure.
260    #[must_use]
261    pub const fn is_error(&self) -> bool {
262        !self.is_ok()
263    }
264
265    /// Returns the corresponding Response object ID.
266    #[must_use]
267    pub const fn id(&self) -> &Id {
268        &self.id
269    }
270
271    /// Returns the `result` value, if present.
272    #[must_use]
273    pub const fn result(&self) -> Option<&Value> {
274        match &self.kind {
275            Kind::Ok { result } => Some(result),
276            Kind::Err { .. } => None,
277        }
278    }
279
280    /// Returns the `error` object, if present.
281    #[must_use]
282    pub const fn error(&self) -> Option<&Error> {
283        match &self.kind {
284            Kind::Err { error } => Some(error),
285            Kind::Ok { .. } => None,
286        }
287    }
288}