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