use crate::{
CapabilityError, CapabilityRequest, CapabilityResponse, CapabilityResult,
LocalCapabilityHandler,
};
use appcore_core::{CapabilityDescriptor, CapabilityName};
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Clone)]
pub struct LocalCapabilityProvider {
descriptor: CapabilityDescriptor,
handler: Arc<dyn LocalCapabilityHandler>,
}
impl std::fmt::Debug for LocalCapabilityProvider {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LocalCapabilityProvider")
.field("descriptor", &self.descriptor)
.finish_non_exhaustive()
}
}
impl LocalCapabilityProvider {
pub(crate) fn new(
descriptor: CapabilityDescriptor,
handler: Arc<dyn LocalCapabilityHandler>,
) -> Self {
Self {
descriptor,
handler,
}
}
pub fn descriptor(&self) -> &CapabilityDescriptor {
&self.descriptor
}
pub fn is_healthy(&self) -> bool {
self.handler.is_healthy()
}
pub fn handle(&self, request: &CapabilityRequest) -> CapabilityResult<CapabilityResponse> {
self.handler.handle(request)
}
}
#[derive(Debug, Clone, Default)]
pub struct CapabilityRegistry {
local: HashMap<CapabilityName, LocalCapabilityProvider>,
}
impl CapabilityRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn register_handler<H>(&mut self, handler: H) -> CapabilityResult<()>
where
H: LocalCapabilityHandler + 'static,
{
self.register_shared_handler(Arc::new(handler))
}
pub fn register_shared_handler(
&mut self,
handler: Arc<dyn LocalCapabilityHandler>,
) -> CapabilityResult<()> {
let descriptor = handler.descriptor();
if self.local.contains_key(&descriptor.name) {
return Err(CapabilityError::HandlerAlreadyRegistered(
descriptor.name.clone(),
));
}
self.local.insert(
descriptor.name.clone(),
LocalCapabilityProvider::new(descriptor, handler),
);
Ok(())
}
pub fn get(&self, capability: &CapabilityName) -> Option<&LocalCapabilityProvider> {
self.local.get(capability)
}
pub fn descriptors(&self) -> Vec<CapabilityDescriptor> {
self.local
.values()
.map(|provider| provider.descriptor.clone())
.collect()
}
}