diff options
Diffstat (limited to 'support/texlab/src/dispatch.rs')
-rw-r--r-- | support/texlab/src/dispatch.rs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/support/texlab/src/dispatch.rs b/support/texlab/src/dispatch.rs new file mode 100644 index 0000000000..a080016480 --- /dev/null +++ b/support/texlab/src/dispatch.rs @@ -0,0 +1,81 @@ +use anyhow::Result; +use log::warn; +use lsp_server::{ErrorCode, Notification, Request, RequestId, Response}; +use serde::de::DeserializeOwned; + +pub struct NotificationDispatcher { + not: Option<Notification>, +} + +impl NotificationDispatcher { + pub fn new(not: Notification) -> Self { + Self { not: Some(not) } + } + + pub fn on<N, F>(mut self, handler: F) -> Result<Self> + where + N: lsp_types::notification::Notification, + N::Params: DeserializeOwned, + F: FnOnce(N::Params) -> Result<()>, + { + if let Some(not) = self.not { + match not.extract::<N::Params>(N::METHOD) { + Ok(params) => { + handler(params)?; + self.not = None; + } + Err(not) => { + self.not = Some(not); + } + }; + } + Ok(self) + } + + pub fn default(self) { + if let Some(not) = &self.not { + warn!("Unknown notification: {}", not.method); + } + } +} + +pub struct RequestDispatcher { + req: Option<Request>, +} + +impl RequestDispatcher { + pub fn new(req: Request) -> Self { + Self { req: Some(req) } + } + + pub fn on<R, F>(mut self, handler: F) -> Result<Self> + where + R: lsp_types::request::Request, + R::Params: DeserializeOwned, + F: FnOnce(RequestId, R::Params) -> Result<()>, + { + if let Some(req) = self.req { + match req.extract::<R::Params>(R::METHOD) { + Ok((id, params)) => { + handler(id, params)?; + self.req = None; + } + Err(req) => { + self.req = Some(req); + } + } + } + Ok(self) + } + + pub fn default(self) -> Option<Response> { + self.req.map(|req| { + warn!("Unknown request: {}", req.method); + Response::new_err( + req.id, + ErrorCode::MethodNotFound as i32, + "method not found".to_string(), + ) + }) + } +} |