sword_core/injectables/
components.rs1use crate::{DependencyInjectionError, HasDeps, Injectable, RwMap, State};
2use std::{
3 any::{TypeId, type_name},
4 collections::HashMap,
5 sync::Arc,
6};
7
8type ComponentBuilderFn = Box<dyn Fn(&State) -> Result<Injectable, DependencyInjectionError>>;
9
10pub trait Component: HasDeps {}
18
19pub struct ComponentRegistry {
20 builders: RwMap<TypeId, ComponentBuilderFn>,
21 dependency_graph: RwMap<TypeId, Vec<TypeId>>,
22}
23
24impl ComponentRegistry {
25 pub(crate) fn new() -> Self {
26 Self {
27 builders: RwMap::new(HashMap::new()),
28 dependency_graph: RwMap::new(HashMap::new()),
29 }
30 }
31
32 pub fn register<T: Component>(&self) {
33 let type_id = TypeId::of::<T>();
34 let type_name = type_name::<T>();
35
36 let component_builder = Box::new(move |state: &State| {
37 T::build(state)
38 .map(|instance| Arc::new(instance) as Injectable)
39 .map_err(|e| DependencyInjectionError::build_failed(type_name, e))
40 });
41
42 self.dependency_graph.write().insert(type_id, T::deps());
43 self.builders.write().insert(type_id, component_builder);
44 }
45
46 pub(crate) fn get_builders(&self) -> &RwMap<TypeId, ComponentBuilderFn> {
47 &self.builders
48 }
49
50 pub(crate) fn get_dependency_graph(&self) -> &RwMap<TypeId, Vec<TypeId>> {
51 &self.dependency_graph
52 }
53}