summaryrefslogtreecommitdiff
path: root/support/texlab/crates/jsonrpc/src/client.rs
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-12-03 03:01:24 +0000
committerNorbert Preining <norbert@preining.info>2019-12-03 03:01:24 +0000
commitb8d4bb76703bcb15578e2b23c5d256532180b894 (patch)
treebedd1df7a00521a2bd986b3c0289d6556a59e39b /support/texlab/crates/jsonrpc/src/client.rs
parent02e4625a78a5029e8b5dc2a4ec70193b232f497e (diff)
CTAN sync 201912030301
Diffstat (limited to 'support/texlab/crates/jsonrpc/src/client.rs')
-rw-r--r--support/texlab/crates/jsonrpc/src/client.rs74
1 files changed, 74 insertions, 0 deletions
diff --git a/support/texlab/crates/jsonrpc/src/client.rs b/support/texlab/crates/jsonrpc/src/client.rs
new file mode 100644
index 0000000000..2cf18af1ff
--- /dev/null
+++ b/support/texlab/crates/jsonrpc/src/client.rs
@@ -0,0 +1,74 @@
+use crate::types::*;
+use chashmap::CHashMap;
+use futures::channel::*;
+use futures::prelude::*;
+use futures_boxed::boxed;
+use serde::Serialize;
+use serde_json::json;
+use std::sync::atomic::{AtomicU64, Ordering};
+
+pub type Result<T> = std::result::Result<T, Error>;
+
+pub trait ResponseHandler {
+ #[boxed]
+ async fn handle(&self, response: Response);
+}
+
+pub struct Client {
+ output: mpsc::Sender<String>,
+ request_id: AtomicU64,
+ senders_by_id: CHashMap<Id, oneshot::Sender<Result<serde_json::Value>>>,
+}
+
+impl Client {
+ pub fn new(output: mpsc::Sender<String>) -> Self {
+ Client {
+ output,
+ request_id: AtomicU64::new(0),
+ senders_by_id: CHashMap::new(),
+ }
+ }
+
+ pub async fn send_request<T: Serialize>(
+ &self,
+ method: String,
+ params: T,
+ ) -> Result<serde_json::Value> {
+ let id = self.request_id.fetch_add(1, Ordering::SeqCst);
+ let request = Request::new(method, json!(params), Id::Number(id));
+
+ let (result_tx, result_rx) = oneshot::channel();
+ self.senders_by_id.insert(request.id.clone(), result_tx);
+ self.send(Message::Request(request)).await;
+
+ result_rx.await.unwrap()
+ }
+
+ pub async fn send_notification<T: Serialize>(&self, method: String, params: T) {
+ let notification = Notification::new(method, json!(params));
+ self.send(Message::Notification(notification)).await;
+ }
+
+ async fn send(&self, message: Message) {
+ let mut output = self.output.clone();
+ let json = serde_json::to_string(&message).unwrap();
+ output.send(json).await.unwrap();
+ }
+}
+
+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 {
+ Some(why) => Err(why),
+ None => Ok(response.result.unwrap_or(serde_json::Value::Null)),
+ };
+
+ let result_tx = self
+ .senders_by_id
+ .remove(&id)
+ .expect("Unexpected response received");
+ result_tx.send(result).unwrap();
+ }
+}