Skip to main content

atomr_core/actor/
extensions.rs

1//! Extensions — per-`ActorSystem` singletons keyed by type.
2
3use std::any::{Any, TypeId};
4use std::sync::Arc;
5
6use dashmap::DashMap;
7
8/// Marker trait for types stored in `Extensions`.
9pub trait Extension: Any + Send + Sync {}
10
11impl<T: Any + Send + Sync> Extension for T {}
12
13/// Identifier trait mirroring.
14pub trait ExtensionId<E: Extension>: Send + Sync {
15    fn create(&self) -> E;
16}
17
18#[derive(Debug, Default)]
19pub struct Extensions {
20    inner: DashMap<TypeId, Arc<dyn Any + Send + Sync>>,
21}
22
23impl Extensions {
24    pub fn new() -> Self {
25        Self::default()
26    }
27
28    pub fn register<E: Extension>(&self, ext: E) {
29        self.inner.insert(TypeId::of::<E>(), Arc::new(ext));
30    }
31
32    pub fn get<E: Extension>(&self) -> Option<Arc<E>> {
33        self.inner.get(&TypeId::of::<E>()).and_then(|e| e.clone().downcast::<E>().ok())
34    }
35
36    pub fn get_or_create<E: Extension, I: ExtensionId<E>>(&self, id: &I) -> Arc<E> {
37        if let Some(e) = self.get::<E>() {
38            return e;
39        }
40        let ext = id.create();
41        self.register(ext);
42        self.get::<E>().expect("just inserted")
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    struct Metrics(u32);
51    struct MetricsId;
52    impl ExtensionId<Metrics> for MetricsId {
53        fn create(&self) -> Metrics {
54            Metrics(99)
55        }
56    }
57
58    #[test]
59    fn create_and_get() {
60        let e = Extensions::new();
61        let m = e.get_or_create::<Metrics, _>(&MetricsId);
62        assert_eq!(m.0, 99);
63        assert!(e.get::<Metrics>().is_some());
64    }
65}