atomr_core/actor/
extensions.rs1use std::any::{Any, TypeId};
4use std::sync::Arc;
5
6use dashmap::DashMap;
7
8pub trait Extension: Any + Send + Sync {}
10
11impl<T: Any + Send + Sync> Extension for T {}
12
13pub 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}