1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
use std::borrow::Cow;
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value;
use super::{Id, Version};
fn deserialize_some<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(Some)
}
/// A JSON-RPC request or notification.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Request {
jsonrpc: Version,
#[serde(default)]
method: Cow<'static, str>,
#[serde(default, deserialize_with = "deserialize_some")]
#[serde(skip_serializing_if = "Option::is_none")]
params: Option<Value>,
#[serde(default, deserialize_with = "deserialize_some")]
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<Id>,
}
impl Request {
/// Starts building a JSON-RPC method call.
///
/// Returns a `RequestBuilder`, which allows setting the `params` field or adding a request ID.
pub fn build<M>(method: M) -> RequestBuilder
where
M: Into<Cow<'static, str>>,
{
RequestBuilder {
method: method.into(),
params: None,
id: None,
}
}
/// Constructs a JSON-RPC request from its corresponding LSP type.
///
/// # Panics
///
/// Panics if `params` could not be serialized into a [`serde_json::Value`]. Since the
/// [`lsp_types::request::Request`] trait promises this invariant is upheld, this should never
/// happen in practice (unless the trait was implemented incorrectly).
pub(crate) fn from_request<R>(id: Id, params: R::Params) -> Self
where
R: lsp_types::request::Request,
{
Request {
jsonrpc: Version,
method: R::METHOD.into(),
params: Some(serde_json::to_value(params).unwrap()),
id: Some(id),
}
}
/// Constructs a JSON-RPC notification from its corresponding LSP type.
///
/// # Panics
///
/// Panics if `params` could not be serialized into a [`serde_json::Value`]. Since the
/// [`lsp_types::notification::Notification`] trait promises this invariant is upheld, this
/// should never happen in practice (unless the trait was implemented incorrectly).
pub(crate) fn from_notification<N>(params: N::Params) -> Self
where
N: lsp_types::notification::Notification,
{
Request {
jsonrpc: Version,
method: N::METHOD.into(),
params: Some(serde_json::to_value(params).unwrap()),
id: None,
}
}
/// Returns the name of the method to be invoked.
pub fn method(&self) -> &str {
self.method.as_ref()
}
/// Returns the unique ID of this request, if present.
pub fn id(&self) -> Option<&Id> {
self.id.as_ref()
}
/// Returns the `params` field, if present.
pub fn params(&self) -> Option<&Value> {
self.params.as_ref()
}
/// Splits this request into the method name, request ID, and the `params` field, if present.
pub fn into_parts(self) -> (Cow<'static, str>, Option<Id>, Option<Value>) {
(self.method, self.id, self.params)
}
}
impl Display for Request {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use std::{io, str};
struct WriterFormatter<'a, 'b: 'a> {
inner: &'a mut Formatter<'b>,
}
impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
fn io_error<E>(_: E) -> io::Error {
// Error value does not matter because fmt::Display impl below just
// maps it to fmt::Error
io::Error::new(io::ErrorKind::Other, "fmt error")
}
let s = str::from_utf8(buf).map_err(io_error)?;
self.inner.write_str(s).map_err(io_error)?;
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
let mut w = WriterFormatter { inner: f };
serde_json::to_writer(&mut w, self).map_err(|_| fmt::Error)
}
}
impl FromStr for Request {
type Err = serde_json::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
serde_json::from_str(s)
}
}
/// A builder to construct the properties of a `Request`.
///
/// To construct a `RequestBuilder`, refer to [`Request::build`].
#[derive(Debug)]
pub struct RequestBuilder {
method: Cow<'static, str>,
params: Option<Value>,
id: Option<Id>,
}
impl RequestBuilder {
/// Sets the `id` member of the request to the given value.
///
/// If this method is not called, the resulting `Request` will be assumed to be a notification.
pub fn id<I: Into<Id>>(mut self, id: I) -> Self {
self.id = Some(id.into());
self
}
/// Sets the `params` member of the request to the given value.
///
/// This member is omitted from the request by default.
pub fn params<V: Into<Value>>(mut self, params: V) -> Self {
self.params = Some(params.into());
self
}
/// Constructs the JSON-RPC request and returns it.
pub fn finish(self) -> Request {
Request {
jsonrpc: Version,
method: self.method,
params: self.params,
id: self.id,
}
}
}