use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use super::dctx::DharaContext;
pub type HandlerFuture = Pin<Box<dyn Future<Output = HandlerResult> + Send>>;
pub struct HandlerResult {
pub result: String,
pub status: Option<String>,
}
impl HandlerResult {
pub fn ok(result: impl Into<String>) -> Self {
Self { result: result.into(), status: None }
}
pub fn with_status(result: impl Into<String>, status: impl Into<String>) -> Self {
Self { result: result.into(), status: Some(status.into()) }
}
}
pub type DharaHandlerFn = Arc<
dyn Fn(String, DharaContext) -> HandlerFuture + Send + Sync
>;
pub struct DharaFunctionRegistry {
handlers: HashMap<String, DharaHandlerFn>,
}
impl DharaFunctionRegistry {
pub fn new() -> Self {
Self { handlers: HashMap::new() }
}
pub fn register<F, Fut>(&mut self, name: impl Into<String>, handler: F)
where
F: Fn(String, DharaContext) -> Fut + Send + Sync + 'static,
Fut: Future<Output = HandlerResult> + Send + 'static,
{
let handler = Arc::new(move |args: String, ctx: DharaContext| -> HandlerFuture {
Box::pin(handler(args, ctx))
});
self.handlers.insert(name.into(), handler);
}
pub fn get(&self, name: &str) -> Option<&DharaHandlerFn> {
self.handlers.get(name)
}
pub fn contains(&self, name: &str) -> bool {
self.handlers.contains_key(name)
}
pub fn names(&self) -> Vec<&str> {
self.handlers.keys().map(|s| s.as_str()).collect()
}
}