diff options
Diffstat (limited to 'support/texlab/crates/jsonrpc')
-rw-r--r-- | support/texlab/crates/jsonrpc/Cargo.toml | 17 | ||||
-rw-r--r-- | support/texlab/crates/jsonrpc/src/client.rs | 17 | ||||
-rw-r--r-- | support/texlab/crates/jsonrpc/src/lib.rs | 73 | ||||
-rw-r--r-- | support/texlab/crates/jsonrpc/src/server.rs | 68 | ||||
-rw-r--r-- | support/texlab/crates/jsonrpc/src/types.rs | 20 |
5 files changed, 95 insertions, 100 deletions
diff --git a/support/texlab/crates/jsonrpc/Cargo.toml b/support/texlab/crates/jsonrpc/Cargo.toml index d806759f3f..cae7107ae1 100644 --- a/support/texlab/crates/jsonrpc/Cargo.toml +++ b/support/texlab/crates/jsonrpc/Cargo.toml @@ -2,16 +2,19 @@ name = "jsonrpc" version = "0.1.0" authors = [ - "Eric Förster <efoerster@users.noreply.github.com>", - "Patrick Förster <pfoerster@users.noreply.github.com>"] + "Eric Förster <eric.foerster@outlook.com>", + "Patrick Förster <patrick.foerster@outlook.de>"] edition = "2018" +[lib] +doctest = false + [dependencies] +async-trait = "0.1" chashmap = "2.2" -futures-boxed = { path = "../futures_boxed" } -futures-preview = "0.3.0-alpha.18" -log = "0.4.6" -tokio = "0.2.0-alpha.6" -serde = { version = "1.0", features = ["derive"] } +futures = "0.3" +log = "0.4" +serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" serde_repr = "0.1" +tokio = { version = "0.2", features = ["rt-core"] } diff --git a/support/texlab/crates/jsonrpc/src/client.rs b/support/texlab/crates/jsonrpc/src/client.rs index 2cf18af1ff..7d714283c6 100644 --- a/support/texlab/crates/jsonrpc/src/client.rs +++ b/support/texlab/crates/jsonrpc/src/client.rs @@ -1,19 +1,22 @@ -use crate::types::*; +use super::types::*; +use async_trait::async_trait; use chashmap::CHashMap; -use futures::channel::*; -use futures::prelude::*; -use futures_boxed::boxed; +use futures::{ + channel::{mpsc, oneshot}, + prelude::*, +}; use serde::Serialize; use serde_json::json; use std::sync::atomic::{AtomicU64, Ordering}; pub type Result<T> = std::result::Result<T, Error>; +#[async_trait] pub trait ResponseHandler { - #[boxed] async fn handle(&self, response: Response); } +#[derive(Debug)] pub struct Client { output: mpsc::Sender<String>, request_id: AtomicU64, @@ -22,7 +25,7 @@ pub struct Client { impl Client { pub fn new(output: mpsc::Sender<String>) -> Self { - Client { + Self { output, request_id: AtomicU64::new(0), senders_by_id: CHashMap::new(), @@ -56,8 +59,8 @@ impl Client { } } +#[async_trait] impl ResponseHandler for Client { - #[boxed] async fn handle(&self, response: Response) { let id = response.id.expect("Expected response with id"); let result = match response.error { diff --git a/support/texlab/crates/jsonrpc/src/lib.rs b/support/texlab/crates/jsonrpc/src/lib.rs index 8786598d58..3a771e6ba5 100644 --- a/support/texlab/crates/jsonrpc/src/lib.rs +++ b/support/texlab/crates/jsonrpc/src/lib.rs @@ -8,59 +8,54 @@ pub use self::{ types::*, }; -use futures::channel::*; -use futures::prelude::*; +use futures::{channel::mpsc, prelude::*}; use log::error; -use std::io; use std::sync::Arc; -pub struct MessageHandler<S, C, I> { +#[derive(Debug)] +pub struct MessageHandler<S, C> { pub server: Arc<S>, pub client: Arc<C>, - pub input: I, pub output: mpsc::Sender<String>, } -impl<S, C, I> MessageHandler<S, C, I> +impl<S, C> MessageHandler<S, C> where S: RequestHandler + Middleware + Send + Sync + 'static, C: ResponseHandler + Send + Sync + 'static, - I: Stream<Item = io::Result<String>> + Unpin, { - pub async fn listen(&mut self) { - while let Some(json) = self.input.next().await { - self.server.before_message().await; + pub async fn handle(&mut self, json: &str) { + self.server.before_message().await; - match serde_json::from_str(&json.unwrap()).map_err(|_| Error::parse_error()) { - Ok(Message::Request(request)) => { - let server = Arc::clone(&self.server); - let mut output = self.output.clone(); - tokio::spawn(async move { - let response = server.handle_request(request).await; - if let Some(error) = response.error.as_ref() { - error!("{:?}", error); - } - let json = serde_json::to_string(&response).unwrap(); - output.send(json).await.unwrap(); - server.after_message().await; - }); - } - Ok(Message::Notification(notification)) => { - self.server.handle_notification(notification); - self.after_message(); - } - Ok(Message::Response(response)) => { - self.client.handle(response).await; - self.after_message(); - } - Err(why) => { - let response = Response::error(why, None); + match serde_json::from_str(json).map_err(|_| Error::parse_error()) { + Ok(Message::Request(request)) => { + let server = Arc::clone(&self.server); + let mut output = self.output.clone(); + tokio::spawn(async move { + let response = server.handle_request(request).await; + if let Some(error) = response.error.as_ref() { + error!("{:?}", error); + } let json = serde_json::to_string(&response).unwrap(); - self.output.send(json).await.unwrap(); - self.after_message(); - } - }; - } + output.send(json).await.unwrap(); + server.after_message().await; + }); + } + Ok(Message::Notification(notification)) => { + self.server.handle_notification(notification).await; + self.after_message(); + } + Ok(Message::Response(response)) => { + self.client.handle(response).await; + self.after_message(); + } + Err(why) => { + let response = Response::error(why, None); + let json = serde_json::to_string(&response).unwrap(); + self.output.send(json).await.unwrap(); + self.after_message(); + } + }; } fn after_message(&self) { diff --git a/support/texlab/crates/jsonrpc/src/server.rs b/support/texlab/crates/jsonrpc/src/server.rs index ccc04f286e..ce34dc8b60 100644 --- a/support/texlab/crates/jsonrpc/src/server.rs +++ b/support/texlab/crates/jsonrpc/src/server.rs @@ -1,24 +1,22 @@ -use crate::types::*; +use super::types::*; +use async_trait::async_trait; use futures::prelude::*; -use futures_boxed::boxed; -use serde::de::DeserializeOwned; -use serde::Serialize; +use serde::{de::DeserializeOwned, Serialize}; use serde_json::json; pub type Result<T> = std::result::Result<T, String>; +#[async_trait] pub trait RequestHandler { - #[boxed] async fn handle_request(&self, request: Request) -> Response; - fn handle_notification(&self, notification: Notification); + async fn handle_notification(&self, notification: Notification); } +#[async_trait] pub trait Middleware { - #[boxed] async fn before_message(&self); - #[boxed] async fn after_message(&self); } @@ -29,12 +27,10 @@ where I: DeserializeOwned + Send, O: Serialize, { - let handle = |json| { - async move { - let params: I = serde_json::from_value(json).map_err(|_| Error::deserialize_error())?; - let result = handler(params).await.map_err(Error::internal_error)?; - Ok(result) - } + let handle = |json| async move { + let params: I = serde_json::from_value(json).map_err(|_| Error::deserialize_error())?; + let result = handler(params).await.map_err(Error::internal_error)?; + Ok(result) }; match handle(request.params).await { @@ -43,20 +39,20 @@ where } } -pub fn handle_notification<'a, H, I>(notification: Notification, handler: H) +pub async fn handle_notification<'a, H, F, I>(notification: Notification, handler: H) where - H: Fn(I) -> () + Send + Sync + 'a, + H: Fn(I) -> F + Send + Sync + 'a, + F: Future<Output = ()> + Send, I: DeserializeOwned + Send, { - let params = - serde_json::from_value(notification.params).expect(&Error::deserialize_error().message); - handler(params); + let error = Error::deserialize_error().message; + let params = serde_json::from_value(notification.params).expect(&error); + handler(params).await; } #[cfg(test)] mod tests { use super::*; - use futures::executor::block_on; const METHOD_NAME: &str = "foo"; @@ -64,7 +60,7 @@ mod tests { Ok(i + 1) } - fn panic(_params: ()) { + async fn panic(_params: ()) { panic!("success"); } @@ -85,15 +81,15 @@ mod tests { } } - #[test] - fn test_request_valid() { + #[tokio::test] + async fn request_valid() { let value = 42; let request = setup_request(value); - let response = block_on(handle_request(request.clone(), increment)); + let response = handle_request(request.clone(), increment).await; let expected = Response { jsonrpc: request.jsonrpc, - result: Some(json!(block_on(increment(value)).unwrap())), + result: Some(json!(increment(value).await.unwrap())), error: None, id: Some(request.id), }; @@ -101,11 +97,11 @@ mod tests { assert_eq!(response, expected); } - #[test] - fn test_request_invalid_params() { + #[tokio::test] + async fn request_invalid_params() { let request = setup_request((0, 0)); - let response = block_on(handle_request(request.clone(), increment)); + let response = handle_request(request.clone(), increment).await; let expected = Response { jsonrpc: request.jsonrpc.clone(), result: None, @@ -116,22 +112,20 @@ mod tests { assert_eq!(response, expected); } - #[test] + #[tokio::test] #[should_panic(expected = "success")] - fn test_notification_valid() { + async fn notification_valid() { let notification = setup_notification(); - handle_notification(notification, panic); + handle_notification(notification, panic).await; } - #[test] + #[tokio::test] #[should_panic] - fn test_notification_invalid_params() { - let notification = setup_notification(); + async fn notification_invalid_params() { let notification = Notification { params: json!(0), - ..notification + ..setup_notification() }; - - handle_notification(notification, panic); + handle_notification(notification, panic).await; } } diff --git a/support/texlab/crates/jsonrpc/src/types.rs b/support/texlab/crates/jsonrpc/src/types.rs index 90116ac793..30036d1c7f 100644 --- a/support/texlab/crates/jsonrpc/src/types.rs +++ b/support/texlab/crates/jsonrpc/src/types.rs @@ -28,8 +28,8 @@ pub struct Error { pub code: ErrorCode, pub message: String, - #[serde(skip_serializing_if = "serde_json::Value::is_null")] - pub data: serde_json::Value, + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option<serde_json::Value>, } impl Error { @@ -37,7 +37,7 @@ impl Error { Self { code: ErrorCode::ParseError, message: "Could not parse the input".to_owned(), - data: serde_json::Value::Null, + data: None, } } @@ -45,7 +45,7 @@ impl Error { Self { code: ErrorCode::MethodNotFound, message: "Method not found".to_owned(), - data: serde_json::Value::Null, + data: None, } } @@ -53,7 +53,7 @@ impl Error { Self { code: ErrorCode::InvalidParams, message: "Could not deserialize parameter object".to_owned(), - data: serde_json::Value::Null, + data: None, } } @@ -61,7 +61,7 @@ impl Error { Self { code: ErrorCode::InternalError, message, - data: serde_json::Value::Null, + data: None, } } } @@ -76,7 +76,7 @@ pub struct Request { impl Request { pub fn new(method: String, params: serde_json::Value, id: Id) -> Self { - Request { + Self { jsonrpc: PROTOCOL_VERSION.to_owned(), method, params, @@ -100,7 +100,7 @@ pub struct Response { impl Response { pub fn result(result: serde_json::Value, id: Id) -> Self { - Response { + Self { jsonrpc: PROTOCOL_VERSION.to_owned(), result: Some(result), error: None, @@ -109,7 +109,7 @@ impl Response { } pub fn error(error: Error, id: Option<Id>) -> Self { - Response { + Self { jsonrpc: PROTOCOL_VERSION.to_owned(), result: None, error: Some(error), @@ -127,7 +127,7 @@ pub struct Notification { impl Notification { pub fn new(method: String, params: serde_json::Value) -> Self { - Notification { + Self { jsonrpc: PROTOCOL_VERSION.to_owned(), method, params, |