From b8d4bb76703bcb15578e2b23c5d256532180b894 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Tue, 3 Dec 2019 03:01:24 +0000 Subject: CTAN sync 201912030301 --- support/texlab/crates/jsonrpc/src/client.rs | 74 +++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 support/texlab/crates/jsonrpc/src/client.rs (limited to 'support/texlab/crates/jsonrpc/src/client.rs') 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 = std::result::Result; + +pub trait ResponseHandler { + #[boxed] + async fn handle(&self, response: Response); +} + +pub struct Client { + output: mpsc::Sender, + request_id: AtomicU64, + senders_by_id: CHashMap>>, +} + +impl Client { + pub fn new(output: mpsc::Sender) -> Self { + Client { + output, + request_id: AtomicU64::new(0), + senders_by_id: CHashMap::new(), + } + } + + pub async fn send_request( + &self, + method: String, + params: T, + ) -> Result { + 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(&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(); + } +} -- cgit v1.2.3