summaryrefslogtreecommitdiff
path: root/support/texlab/crates/jsonrpc
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/crates/jsonrpc')
-rw-r--r--support/texlab/crates/jsonrpc/Cargo.toml17
-rw-r--r--support/texlab/crates/jsonrpc/src/client.rs17
-rw-r--r--support/texlab/crates/jsonrpc/src/lib.rs73
-rw-r--r--support/texlab/crates/jsonrpc/src/server.rs68
-rw-r--r--support/texlab/crates/jsonrpc/src/types.rs20
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,