fusion_core/component/
mod.rs1#![doc = include_str!("../../DI.md")]
2mod error;
3
4pub use fusion_core_macros::Component;
5pub use inventory::submit;
6use log::debug;
7use std::{any::Any, collections::HashSet, ops::Deref, sync::Arc};
8
9use crate::application::ApplicationBuilder;
10
11pub use error::{ComponentError, ComponentResult};
12
13#[derive(Debug, Clone)]
15pub struct DynComponentArc(Arc<dyn Any + Send + Sync>);
16
17impl DynComponentArc {
18 pub fn new<T>(component: T) -> Self
20 where
21 T: Any + Send + Sync,
22 {
23 Self(Arc::new(component))
24 }
25
26 pub fn downcast<T>(self) -> ComponentResult<ComponentArc<T>>
28 where
29 T: Any + Send + Sync,
30 {
31 match self.0.downcast::<T>() {
32 Ok(item) => Ok(ComponentArc::new(item)),
33 Err(_) => Err(ComponentError::ComponentTypeMismatch(std::any::type_name::<T>())),
34 }
35 }
36}
37
38#[derive(Debug, Clone)]
40pub struct ComponentArc<T>(Arc<T>);
41
42impl<T> ComponentArc<T> {
43 fn new(target_ref: Arc<T>) -> Self {
44 Self(target_ref)
45 }
46
47 #[inline]
49 pub fn into_raw(self) -> *const T {
50 Arc::into_raw(self.0)
51 }
52}
53
54impl<T> Deref for ComponentArc<T> {
55 type Target = T;
56
57 fn deref(&self) -> &Self::Target {
58 &self.0
59 }
60}
61
62pub trait Component: Clone + Sized + 'static {
63 fn build(app: &ApplicationBuilder) -> crate::Result<Self>;
65}
66
67pub trait ComponentInstaller: Send + Sync + 'static {
68 fn dependencies(&self) -> Vec<&str>;
70
71 fn install_component(&self, app: &mut ApplicationBuilder) -> crate::Result<()>;
73}
74
75inventory::collect!(&'static dyn ComponentInstaller);
76
77#[macro_export]
79macro_rules! submit_component {
80 ($ty:tt) => {
81 ::fusion_core::component::submit! {
82 &($ty) as &dyn ::fusion_core::component::ComponentInstaller
83 }
84 };
85}
86
87pub fn auto_inject_component(app_builder: &mut ApplicationBuilder) -> crate::Result<()> {
89 let mut registrars: Vec<(&&dyn ComponentInstaller, Vec<&str>)> =
90 inventory::iter::<&dyn ComponentInstaller>.into_iter().map(|cr| (cr, cr.dependencies())).collect();
91
92 let mut epoch = 0;
94 let mut last_pending_len = 0;
95
96 while !registrars.is_empty() && epoch < 10 {
97 let mut pending_registrars = vec![];
98 for (registrar, deps) in registrars {
99 let deps: Vec<&str> = deps.into_iter().filter(|d| !app_builder.components.contains_key(*d)).collect();
100 if deps.is_empty() {
101 registrar.install_component(app_builder)?;
102 } else {
103 debug!("Dependency does not exist, waiting for the next round: [{:?}]", deps);
104 pending_registrars.push((registrar, deps));
105 }
106 }
107 registrars = pending_registrars;
108
109 let pending_len = registrars.len();
110 if pending_len == 0 || last_pending_len != pending_len {
111 epoch = 0;
112 last_pending_len = pending_len;
113 } else {
114 epoch += 1;
115 }
116 }
117 if epoch != 0 {
118 let deps: HashSet<&str> = registrars.iter().flat_map(|(_, deps)| deps).copied().collect();
119 panic!(
120 "Component registration failed, please check the component dependency relationship. Unregistered Components: {:?}, epoch: {}",
121 deps, epoch
122 );
123 }
124 Ok(())
125}