1use fxhash::FxHashMap;
2use log::error;
3use springtime_di::component::Injectable;
4use springtime_di::component_registry::ComponentAliasMetadata;
5use springtime_di::component_registry::ComponentDefinition;
6use springtime_di::component_registry::ComponentDefinitionRegistry;
7use springtime_di::component_registry::ComponentDefinitionRegistryError;
8use springtime_di::component_registry::ComponentMetadata;
9use springtime_di::component_registry::StaticComponentDefinitionRegistry;
10use springtime_di::component_registry::conditional::SimpleContextFactory;
11use springtime_di::factory::ComponentFactory;
12use springtime_di::factory::ScopeFactoryPtr;
13use springtime_di::instance_provider::CastFunction;
14use springtime_di::instance_provider::ComponentInstanceAnyPtr;
15use springtime_di::instance_provider::ComponentInstanceProvider;
16use springtime_di::instance_provider::ComponentInstanceProviderError;
17use springtime_di::instance_provider::TypedComponentInstanceProvider;
18use springtime_di::scope::PROTOTYPE;
19use springtime_di::scope::PrototypeScopeFactory;
20use springtime_di::scope::SINGLETON;
21use springtime_di::scope::SingletonScopeFactory;
22use std::any::TypeId;
23use std::sync::Arc;
24use std::sync::LazyLock;
25use std::sync::RwLock;
26
27pub static STATIC_COMPONENT_DEFINITION_REGISTRY_WRAPPER: LazyLock<Option<Arc<StaticComponentDefinitionRegistryWrapper>>> = LazyLock::new(|| {
28 StaticComponentDefinitionRegistry::new(true, &SimpleContextFactory)
29 .ok()
30 .map(|definition_registry| Arc::new(StaticComponentDefinitionRegistryWrapper::new(definition_registry)))
31});
32
33pub static SHARED_COMPONENT_DEFINITION_REGISTRY: LazyLock<Option<Box<SharedComponentDefinitionRegistry>>> = LazyLock::new(|| {
34 STATIC_COMPONENT_DEFINITION_REGISTRY_WRAPPER
35 .clone()
36 .map(|parent_definition_registry| Box::new(SharedComponentDefinitionRegistry::new(parent_definition_registry.clone())))
37});
38
39#[allow(clippy::let_and_return)]
40pub fn get_shared_component_definition_registry() -> Option<Box<SharedComponentDefinitionRegistry>> {
41 let shared_component_definition_registry = SHARED_COMPONENT_DEFINITION_REGISTRY.clone();
42 shared_component_definition_registry
43}
44
45pub fn get_shared_component_factory() -> ComponentFactory {
46 let Some(definition_registry) = get_shared_component_definition_registry() else {
47 panic!("Failed to initialize the shared component definition registry!");
48 };
49 ComponentFactory::new(
50 definition_registry,
51 [
52 (SINGLETON.to_string(), Box::<SingletonScopeFactory>::default() as ScopeFactoryPtr),
53 (PROTOTYPE.to_string(), Box::<PrototypeScopeFactory>::default() as ScopeFactoryPtr),
54 ]
55 .into_iter()
56 .collect(),
57 )
58}
59
60pub fn get_container<T>() -> Arc<T>
61where
62 T: Injectable + ?Sized + Send + Sync,
63{
64 let mut component_factory = get_shared_component_factory();
65 match TypedComponentInstanceProvider::primary_instance_typed::<T>(&mut component_factory) {
67 Ok(runtime) => runtime,
68 Err(ComponentInstanceProviderError::NoPrimaryInstance { type_id, type_name }) => {
72 error!("Missing component {type_name:?}");
73 let instances: Result<Vec<(ComponentInstanceAnyPtr, CastFunction)>, ComponentInstanceProviderError> = component_factory.instances(type_id);
74 match instances {
75 Ok(instances) => {
76 error!("Component factory has {} instances of type {:?}", instances.len(), type_id);
77 for (component_instance, _) in instances {
78 error!(" Type Id: {:?}", component_instance.type_id());
79 }
80 }
81 Err(e) => {
82 error!("None. {e:?}");
83 }
84 }
85 panic!("Cannot find a primary instance for component '{type_id:?}/{type_name:?}' - either none or multiple exists without a primary marker.");
86 }
87 Err(ComponentInstanceProviderError::IncompatibleComponent { type_id, type_name }) => {
88 panic!("Tried to downcast component to incompatible type: {type_id:?}/{type_name}");
89 }
90 Err(ComponentInstanceProviderError::NoNamedInstance(type_name)) => {
91 panic!("Cannot find named component: {type_name}");
92 }
93 Err(ComponentInstanceProviderError::UnrecognizedScope(scope)) => {
94 panic!("Unrecognized scope: {scope}");
95 }
96 Err(ComponentInstanceProviderError::DependencyCycle { type_id, type_name }) => {
97 panic!("Detected dependency cycle for: {type_id:?}/{type_name:?}");
98 }
99 Err(ComponentInstanceProviderError::ConstructorError(constructor_error)) => {
100 panic!("Error in component constructor: {constructor_error}");
101 }
102 }
103}
104
105#[derive(Debug)]
106pub struct StaticComponentDefinitionRegistryWrapper {
107 pub definition_registry: RwLock<StaticComponentDefinitionRegistry>,
108}
109
110impl StaticComponentDefinitionRegistryWrapper {
111 pub fn new(definition_registry: StaticComponentDefinitionRegistry) -> Self {
112 Self {
113 definition_registry: RwLock::new(definition_registry),
114 }
115 }
116}
117
118#[derive(Clone, Debug)]
119pub struct SharedComponentDefinitionRegistry {
120 definition_registry: Arc<StaticComponentDefinitionRegistryWrapper>,
121}
122
123impl SharedComponentDefinitionRegistry {
124 pub fn new(definition_registry: Arc<StaticComponentDefinitionRegistryWrapper>) -> Self {
125 Self { definition_registry }
126 }
127}
128
129impl ComponentDefinitionRegistry for SharedComponentDefinitionRegistry {
130 #[inline]
131 fn register_component(&mut self, target: TypeId, target_name: &str, metadata: &ComponentMetadata) -> Result<(), ComponentDefinitionRegistryError> {
132 {
133 let mut parent_definition_registry = self.definition_registry.definition_registry.write().unwrap();
134 parent_definition_registry.register_component(target, target_name, metadata)
135 }
136 }
137
138 #[inline]
139 fn register_alias(
140 &mut self,
141 alias_type: TypeId,
142 target_type: TypeId,
143 alias_name: &str,
144 target_name: &str,
145 metadata: &ComponentAliasMetadata,
146 ) -> Result<(), ComponentDefinitionRegistryError> {
147 {
148 let mut parent_definition_registry = self.definition_registry.definition_registry.write().unwrap();
149 parent_definition_registry.register_alias(alias_type, target_type, alias_name, target_name, metadata)
150 }
151 }
152
153 #[inline]
154 fn components_by_type(&self, type_id: TypeId) -> Vec<ComponentDefinition> {
155 {
156 let parent_definition_registry = self.definition_registry.definition_registry.read().unwrap();
157 parent_definition_registry.components_by_type(type_id)
158 }
159 }
160
161 #[inline]
162 fn component_by_name(&self, name: &str, type_id: TypeId) -> Option<ComponentDefinition> {
163 {
164 let parent_definition_registry = self.definition_registry.definition_registry.read().unwrap();
165 parent_definition_registry.component_by_name(name, type_id)
166 }
167 }
168
169 #[inline]
170 fn primary_component(&self, type_id: TypeId) -> Option<ComponentDefinition> {
171 {
172 let parent_definition_registry = self.definition_registry.definition_registry.read().unwrap();
173 parent_definition_registry.primary_component(type_id)
174 }
175 }
176
177 #[inline]
178 fn is_registered(&self, type_id: TypeId) -> bool {
179 {
180 let parent_definition_registry = self.definition_registry.definition_registry.read().unwrap();
181 parent_definition_registry.is_registered(type_id)
182 }
183 }
184
185 #[inline]
186 fn is_name_registered(&self, name: &str) -> bool {
187 {
188 let parent_definition_registry = self.definition_registry.definition_registry.read().unwrap();
189 parent_definition_registry.is_name_registered(name)
190 }
191 }
192
193 #[inline]
194 fn all_definitions(&self) -> FxHashMap<TypeId, Vec<ComponentDefinition>> {
195 {
196 let parent_definition_registry = self.definition_registry.definition_registry.read().unwrap();
197 parent_definition_registry.all_definitions()
198 }
199 }
200}