diff options
author | Norbert Preining <norbert@preining.info> | 2019-12-03 03:01:24 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-12-03 03:01:24 +0000 |
commit | b8d4bb76703bcb15578e2b23c5d256532180b894 (patch) | |
tree | bedd1df7a00521a2bd986b3c0289d6556a59e39b /support/texlab/crates/jsonrpc/src/client.rs | |
parent | 02e4625a78a5029e8b5dc2a4ec70193b232f497e (diff) |
CTAN sync 201912030301
Diffstat (limited to 'support/texlab/crates/jsonrpc/src/client.rs')
-rw-r--r-- | support/texlab/crates/jsonrpc/src/client.rs | 74 |
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(); + } +} |