Skip to main content

rust_dicore/
bridge.rs

1//! Bridge implementations that adapt RDI types to the `sdk::ServiceLocator` trait.
2//!
3//! The `ServiceLocatorBridge` combines:
4//! 1. RDI provider (compile-time registered services, type_name-based)
5//! 2. Named service registry (string-based, for cross-DLL access) —
6//!    stored directly in `ServiceProvider::named`.
7
8use std::any::Any;
9use std::sync::Arc;
10
11use crate::service_locator::{INamedRegistrar, IServiceLocator};
12
13use crate::entry::IServiceResolver;
14use crate::provider::ServiceProvider;
15use crate::wrapper::ServiceProviderWrapper;
16
17/// Enum that wraps either a root `ServiceProvider` or a `ServiceProviderWrapper`
18/// so both can be used interchangeably behind `IServiceResolver`.
19pub enum RdiProvider {
20    Root(Arc<ServiceProvider>),
21    Wrapped(Arc<ServiceProviderWrapper>),
22}
23
24impl IServiceResolver for RdiProvider {
25    fn get_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
26        match self {
27            RdiProvider::Root(p) => IServiceResolver::get_any(p.as_ref(), key),
28            RdiProvider::Wrapped(w) => IServiceResolver::get_any(w.as_ref(), key),
29        }
30    }
31
32    fn get_keyed_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>> {
33        match self {
34            RdiProvider::Root(p) => IServiceResolver::get_keyed_any(p.as_ref(), key, variant),
35            RdiProvider::Wrapped(w) => IServiceResolver::get_keyed_any(w.as_ref(), key, variant),
36        }
37    }
38}
39
40impl RdiProvider {
41    /// Non-generic named resolution for trait-object dispatch.
42    pub fn get_named_any(&self, name: &str) -> Option<Arc<dyn Any + Send + Sync>> {
43        match self {
44            RdiProvider::Root(p) => p.get_named_any(name),
45            RdiProvider::Wrapped(w) => w.get_named_any(name),
46        }
47    }
48
49    /// Register a named service into the active (child) provider.
50    pub fn register_named_any(&self, name: &str, service: Arc<dyn Any + Send + Sync>) {
51        match self {
52            RdiProvider::Root(p) => p.rdi_register_named(name, service),
53            RdiProvider::Wrapped(w) => w.rdi_register_named(name, service),
54        };
55    }
56
57    /// Remove a named service from the active (child) provider.
58    pub fn remove_named(&self, name: &str) {
59        match self {
60            RdiProvider::Root(p) => {
61                p.rdi_remove_named(name);
62            }
63            RdiProvider::Wrapped(w) => {
64                w.rdi_remove_named(name);
65            }
66        }
67    }
68}
69
70/// Bridges RDI into a single `IServiceLocator` implementation.
71///
72/// Resolution order for `get_any`:
73/// 1. RDI provider (compile-time services)
74///
75/// Resolution order for `get_any_named`:
76/// 1. Named registry in RDI provider
77pub struct ServiceLocatorBridge {
78    provider: Arc<RdiProvider>,
79}
80
81impl ServiceLocatorBridge {
82    pub fn new(provider: Arc<RdiProvider>) -> Self {
83        Self { provider }
84    }
85
86    pub fn provider(&self) -> &Arc<RdiProvider> {
87        &self.provider
88    }
89}
90
91impl IServiceLocator for ServiceLocatorBridge {
92    fn get_any(&self, type_key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
93        self.provider.get_any(type_key)
94    }
95
96    fn get_any_named(&self, name: &str) -> Option<Arc<dyn Any + Send + Sync>> {
97        self.provider.get_named_any(name)
98    }
99
100    fn register_named_any(&self, name: &str, service: Arc<dyn Any + Send + Sync>) {
101        self.provider.register_named_any(name, service);
102    }
103
104    fn remove_named(&self, name: &str) {
105        self.provider.remove_named(name);
106    }
107}
108
109impl INamedRegistrar for ServiceLocatorBridge {
110    fn register_named_any(&self, name: &str, service: Arc<dyn Any + Send + Sync>) {
111        self.provider.register_named_any(name, service);
112    }
113
114    fn remove_named(&self, name: &str) {
115        self.provider.remove_named(name);
116    }
117}
118
119/// Implements `IServiceLocator` for standalone RDI types that don't need
120/// the named registry.
121macro_rules! impl_service_locator {
122    ($ty:ty) => {
123        impl IServiceLocator for $ty {
124            fn get_any(&self, type_key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
125                IServiceResolver::get_any(self, type_key)
126            }
127
128            fn get_any_named(&self, name: &str) -> Option<Arc<dyn Any + Send + Sync>> {
129                // Standalone providers may have named services registered.
130                self.get_named_any(name)
131            }
132
133            fn register_named_any(&self, name: &str, service: Arc<dyn Any + Send + Sync>) {
134                self.rdi_register_named(name, service);
135            }
136
137            fn remove_named(&self, name: &str) {
138                self.rdi_remove_named(name);
139            }
140        }
141    };
142}
143
144impl_service_locator!(ServiceProvider);
145impl_service_locator!(crate::scope::Scope);
146impl_service_locator!(ServiceProviderWrapper);