lspkit_server/
dispatch.rs1use std::collections::HashMap;
7use std::pin::Pin;
8use std::sync::{Arc, RwLock};
9
10use serde_json::Value;
11use tokio_util::sync::CancellationToken;
12
13use crate::jsonrpc::{JsonRpcError, RequestId};
14
15type HandlerFuture = Pin<Box<dyn std::future::Future<Output = HandlerResult> + Send>>;
16type HandlerFn = Arc<dyn Fn(Value, CancellationToken) -> HandlerFuture + Send + Sync>;
17
18#[non_exhaustive]
20#[derive(Debug)]
21pub enum HandlerResult {
22 Ok(Value),
24 Err(JsonRpcError),
26}
27
28#[non_exhaustive]
30#[derive(Debug, thiserror::Error)]
31pub enum DispatchError {
32 #[error("method not found: {0}")]
34 UnknownMethod(String),
35}
36
37#[derive(Clone, Default)]
39pub struct Dispatcher {
40 handlers: Arc<RwLock<HashMap<String, HandlerFn>>>,
41 cancellations: Arc<RwLock<HashMap<RequestId, CancellationToken>>>,
42}
43
44impl Dispatcher {
45 #[must_use]
47 pub fn new() -> Self {
48 Self::default()
49 }
50
51 pub fn register<F, Fut>(&self, method: impl Into<String>, handler: F)
53 where
54 F: Fn(Value, CancellationToken) -> Fut + Send + Sync + 'static,
55 Fut: std::future::Future<Output = HandlerResult> + Send + 'static,
56 {
57 let wrapped: HandlerFn = Arc::new(move |params, cancel| Box::pin(handler(params, cancel)));
58 if let Ok(mut guard) = self.handlers.write() {
59 guard.insert(method.into(), wrapped);
60 }
61 }
62
63 pub async fn dispatch(
71 &self,
72 id: &RequestId,
73 method: &str,
74 params: Value,
75 ) -> Result<HandlerResult, DispatchError> {
76 let handler = self
77 .handlers
78 .read()
79 .ok()
80 .and_then(|guard| guard.get(method).cloned())
81 .ok_or_else(|| DispatchError::UnknownMethod(method.to_owned()))?;
82 let cancel = CancellationToken::new();
83 if let Ok(mut guard) = self.cancellations.write() {
84 guard.insert(id.clone(), cancel.clone());
85 }
86 let result = handler(params, cancel).await;
87 if let Ok(mut guard) = self.cancellations.write() {
88 guard.remove(id);
89 }
90 Ok(result)
91 }
92
93 pub fn cancel(&self, id: &RequestId) {
95 if let Ok(guard) = self.cancellations.read() {
96 if let Some(token) = guard.get(id) {
97 token.cancel();
98 }
99 }
100 }
101}
102
103impl std::fmt::Debug for Dispatcher {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 let handlers = self.handlers.read().map_or(0, |g| g.len());
106 let in_flight = self.cancellations.read().map_or(0, |g| g.len());
107 f.debug_struct("Dispatcher")
108 .field("handlers", &handlers)
109 .field("in_flight", &in_flight)
110 .finish()
111 }
112}