Skip to content

Commit ff28d19

Browse files
committed
feat: typed requests
1 parent fd6ecd8 commit ff28d19

22 files changed

+628
-223
lines changed

bsp-server/src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl fmt::Display for ExtractError<Request> {
3535
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3636
match self {
3737
ExtractError::MethodMismatch(req) => {
38-
write!(f, "Method mismatch for request '{}'", req.method)
38+
write!(f, "Method mismatch for request '{}'", req.method())
3939
}
4040
ExtractError::JsonError { method, error } => {
4141
write!(f, "Invalid request\nMethod: {method}\n error: {error}",)

bsp-server/src/lib.rs

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
mod error;
99
mod io_thread;
1010
mod message;
11-
mod req_queue;
11+
// mod req_queue;
1212
mod request;
1313
mod response;
1414
mod transporter;
@@ -21,12 +21,12 @@ pub use error::{ErrorCode, ExtractError, ProtocolError};
2121
pub use io_thread::IoThreads;
2222
pub use message::Message;
2323
pub use notification::Notification;
24-
pub use req_queue::{Incoming, Outgoing, ReqQueue};
24+
// pub use req_queue::{Incoming, Outgoing, ReqQueue};
2525
pub use request::{Request, RequestId};
2626
pub use response::{Response, ResponseError};
2727
pub(crate) use transporter::Transporter;
2828

29-
use bsp_types::InitializeBuildParams;
29+
use bsp_types::InitializeBuild;
3030
use crossbeam_channel::{unbounded, Receiver, SendError, SendTimeoutError, Sender, TrySendError};
3131
use serde::Serialize;
3232
use std::io;
@@ -113,28 +113,26 @@ impl Connection {
113113
#[tracing::instrument(skip_all)]
114114
pub fn initialize<V: Serialize>(
115115
&self,
116-
process: impl FnOnce(&InitializeBuildParams) -> V,
117-
) -> Result<InitializeBuildParams, ProtocolError> {
116+
process: impl FnOnce(&InitializeBuild) -> V,
117+
) -> Result<InitializeBuild, ProtocolError> {
118118
let (id, params) = self.initialize_start()?;
119119
self.initialize_finish(id, process(&params))?;
120120
Ok(params)
121121
}
122122

123123
#[tracing::instrument(skip(self))]
124-
fn initialize_start(&self) -> Result<(RequestId, InitializeBuildParams), ProtocolError> {
124+
fn initialize_start(&self) -> Result<(RequestId, InitializeBuild), ProtocolError> {
125125
loop {
126126
match self.receiver.recv() {
127-
Ok(Message::Request(req)) if req.is_initialize() => {
128-
// WARN: force unwrap
129-
let params = serde_json::from_value(req.params).unwrap();
130-
return Ok((req.id, params));
127+
Ok(Message::Request(Request::InitializeBuild(id, params))) => {
128+
return Ok((id, params));
131129
}
132130
// Respond to non-initialize requests with ServerNotInitialized
133131
Ok(Message::Request(req)) => {
134132
let msg = format!("expected initialize request, got {:?}", req);
135133
tracing::error!("{}", msg);
136134
self.sender
137-
.send(Response::server_not_initialized(req.id.clone(), msg).into())
135+
.send(Response::server_not_initialized(req.id().clone(), msg).into())
138136
.unwrap();
139137
}
140138
Ok(msg) => {
@@ -178,26 +176,27 @@ impl Connection {
178176

179177
/// If `req` is `Shutdown`, respond to it and return `true`, otherwise return `false`
180178
pub fn handle_shutdown(&self, req: &Request) -> Result<bool, ProtocolError> {
181-
if !req.is_shutdown() {
182-
return Ok(false);
183-
}
184-
tracing::info!("processing shutdown server ...");
185-
let resp = Response::ok(req.id.clone(), ());
186-
let _ = self.sender.send(resp.into());
187-
match &self.receiver.recv_timeout(Duration::from_secs(30)) {
188-
Ok(Message::Notification(Notification::Exit)) => (),
189-
Ok(msg) => {
190-
let msg = format!("unexpected message during shutdown: {:?}", msg);
191-
tracing::error!("{}", msg);
179+
if let Request::Shutdown(id) = req {
180+
tracing::info!("processing shutdown server ...");
181+
let resp = Response::ok(id.clone(), ());
182+
let _ = self.sender.send(resp.into());
183+
match &self.receiver.recv_timeout(Duration::from_secs(30)) {
184+
Ok(Message::Notification(Notification::Exit)) => (),
185+
Ok(msg) => {
186+
let msg = format!("unexpected message during shutdown: {:?}", msg);
187+
tracing::error!("{}", msg);
192188

193-
return Err(ProtocolError(msg));
194-
}
195-
Err(e) => {
196-
let msg = format!("unexpected error during shutdown: {}", e);
197-
return Err(ProtocolError(msg));
189+
return Err(ProtocolError(msg));
190+
}
191+
Err(e) => {
192+
let msg = format!("unexpected error during shutdown: {}", e);
193+
return Err(ProtocolError(msg));
194+
}
198195
}
196+
Ok(true)
197+
} else {
198+
Ok(false)
199199
}
200-
Ok(true)
201200
}
202201

203202
/// delegates to self.sender

bsp-server/src/message.rs

Lines changed: 5 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
use crate::Notification;
22
use crate::Request;
33
use crate::Response;
4-
use bsp_types::{
5-
BuildTargetDidChange, LogMessage, PublishDiagnostics, ShowMessage, TaskFinish, TaskProgress,
6-
TaskStart,
7-
};
84
use serde::{Deserialize, Serialize};
9-
use serde_json::Value;
105
use std::io;
116

127
#[derive(Serialize, Deserialize, Debug, Clone)]
@@ -17,18 +12,6 @@ pub enum Message {
1712
Notification(Notification),
1813
}
1914

20-
impl From<Request> for Message {
21-
fn from(request: Request) -> Message {
22-
Message::Request(request)
23-
}
24-
}
25-
26-
impl From<Response> for Message {
27-
fn from(response: Response) -> Message {
28-
Message::Response(response)
29-
}
30-
}
31-
3215
#[derive(Serialize)]
3316
struct JsonRpc {
3417
jsonrpc: &'static str,
@@ -45,36 +28,6 @@ impl From<Message> for JsonRpc {
4528
}
4629
}
4730

48-
macro_rules! from_notification {
49-
($p:ident) => {
50-
impl From<$p> for Message {
51-
fn from(msg: $p) -> Self {
52-
Self::Notification(crate::Notification::$p(msg))
53-
}
54-
}
55-
};
56-
}
57-
58-
impl From<Notification> for Message {
59-
fn from(notification: Notification) -> Self {
60-
Self::Notification(notification)
61-
}
62-
}
63-
64-
impl From<(&'static str, Value)> for Message {
65-
fn from(v: (&'static str, Value)) -> Self {
66-
Self::Notification(Notification::Custom(v.0, v.1))
67-
}
68-
}
69-
70-
from_notification!(ShowMessage);
71-
from_notification!(LogMessage);
72-
from_notification!(PublishDiagnostics);
73-
from_notification!(TaskStart);
74-
from_notification!(TaskFinish);
75-
from_notification!(TaskProgress);
76-
from_notification!(BuildTargetDidChange);
77-
7831
impl Message {
7932
pub(crate) fn read(r: &mut dyn io::BufRead) -> io::Result<Option<Message>> {
8033
let text = match read_msg_text(r)? {
@@ -100,13 +53,12 @@ fn invalid_data(error: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> i
10053
io::Error::new(io::ErrorKind::InvalidData, error)
10154
}
10255

103-
macro_rules! invalid_data {
104-
($($tt:tt)*) => (invalid_data(format!($($tt)*)))
105-
}
56+
macro_rules! invalid_data { ($($tt:tt)*) => (invalid_data(format!($($tt)*))) }
10657

10758
fn read_msg_text(inp: &mut dyn io::BufRead) -> io::Result<Option<String>> {
10859
let mut size = None;
10960
let mut buf = String::new();
61+
11062
loop {
11163
buf.clear();
11264
if inp.read_line(&mut buf)? == 0 {
@@ -128,11 +80,12 @@ fn read_msg_text(inp: &mut dyn io::BufRead) -> io::Result<Option<String>> {
12880
size = Some(header_value.parse::<usize>().map_err(invalid_data)?);
12981
}
13082
}
83+
13184
let size: usize = size.ok_or_else(|| invalid_data!("no Content-Length"))?;
13285
let mut buf = buf.into_bytes();
86+
13387
buf.resize(size, 0);
13488
inp.read_exact(&mut buf)?;
135-
let buf = String::from_utf8(buf).map_err(invalid_data)?;
13689

137-
Ok(Some(buf))
90+
Ok(Some(String::from_utf8(buf).map_err(invalid_data)?))
13891
}

bsp-server/src/notification.rs

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use serde::{
1111
};
1212
use serde_json::Value;
1313

14+
use crate::Message;
15+
1416
#[derive(Debug, Clone)]
1517
pub enum Notification {
1618
Exit,
@@ -43,16 +45,6 @@ impl Notification {
4345
}
4446
}
4547

46-
macro_rules! from_type {
47-
($p:ident) => {
48-
impl From<$p> for Notification {
49-
fn from(msg: $p) -> Self {
50-
Self::$p(msg)
51-
}
52-
}
53-
};
54-
}
55-
5648
impl From<(&'static str, Value)> for Notification {
5749
fn from(v: (&'static str, Value)) -> Self {
5850
Self::Custom(v.0, v.1)
@@ -69,13 +61,40 @@ impl From<&str> for Notification {
6961
}
7062
}
7163

72-
from_type!(ShowMessage);
73-
from_type!(LogMessage);
74-
from_type!(PublishDiagnostics);
75-
from_type!(TaskStart);
76-
from_type!(TaskFinish);
77-
from_type!(TaskProgress);
78-
from_type!(BuildTargetDidChange);
64+
impl From<Notification> for Message {
65+
fn from(notification: Notification) -> Self {
66+
Self::Notification(notification)
67+
}
68+
}
69+
70+
impl From<(&'static str, Value)> for Message {
71+
fn from(v: (&'static str, Value)) -> Self {
72+
Self::Notification(Notification::Custom(v.0, v.1))
73+
}
74+
}
75+
76+
macro_rules! convertible {
77+
($p:ident) => {
78+
impl From<$p> for Notification {
79+
fn from(msg: $p) -> Self {
80+
Self::$p(msg)
81+
}
82+
}
83+
impl From<$p> for Message {
84+
fn from(msg: $p) -> Self {
85+
Self::Notification(crate::Notification::$p(msg))
86+
}
87+
}
88+
};
89+
}
90+
91+
convertible!(ShowMessage);
92+
convertible!(LogMessage);
93+
convertible!(PublishDiagnostics);
94+
convertible!(TaskStart);
95+
convertible!(TaskFinish);
96+
convertible!(TaskProgress);
97+
convertible!(BuildTargetDidChange);
7998

8099
impl Serialize for Notification {
81100
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>

0 commit comments

Comments
 (0)