Skip to main content

axioval_engine/
services.rs

1//! Type-safe host service registration.
2
3use std::{
4    any::{Any, TypeId},
5    collections::HashMap,
6    sync::Arc,
7};
8use thiserror::Error;
9
10/// Service registration failure.
11#[derive(Clone, Copy, Debug, Eq, Error, PartialEq)]
12pub enum ServiceRegistryError {
13    #[error("a service of this type is already registered")]
14    Duplicate,
15}
16
17/// Immutable type-indexed services supplied by an application or adapter.
18#[derive(Clone, Default)]
19pub struct ServiceRegistry {
20    entries: HashMap<TypeId, Arc<dyn Any + Send + Sync>>,
21}
22impl ServiceRegistry {
23    /// Creates an empty registry.
24    #[must_use]
25    pub fn new() -> Self {
26        Self::default()
27    }
28    /// Registers one service without allowing silent replacement.
29    pub fn register<T: Any + Send + Sync>(
30        &mut self,
31        service: T,
32    ) -> Result<(), ServiceRegistryError> {
33        if self.entries.contains_key(&TypeId::of::<T>()) {
34            return Err(ServiceRegistryError::Duplicate);
35        }
36        self.entries.insert(TypeId::of::<T>(), Arc::new(service));
37        Ok(())
38    }
39    /// Looks up a service by its concrete interface type.
40    #[must_use]
41    pub fn get<T: Any + Send + Sync>(&self) -> Option<&T> {
42        self.entries.get(&TypeId::of::<T>())?.downcast_ref()
43    }
44}