1use std::any::{Any, TypeId};
7use std::sync::Arc;
8
9use dashmap::DashMap;
10
11use crate::component::Component;
12use crate::error::{AppError, DiErr};
13
14#[derive(Clone)]
18pub enum CompRef {
19 Factory(Arc<dyn Fn(&Store) -> Arc<dyn Any + Send + Sync> + Send + Sync>),
21 Cached(Arc<dyn Any + Send + Sync>),
23}
24
25pub struct Store {
27 inner: DashMap<TypeId, CompRef>,
28 pub(crate) trait_impls: TraitImplMap,
30}
31
32impl Store {
33 pub fn new() -> Self {
35 Store {
36 inner: DashMap::new(),
37 trait_impls: DashMap::new(),
38 }
39 }
40
41 pub fn from_dashmap(inner: DashMap<TypeId, CompRef>) -> Self {
43 Store {
44 inner,
45 trait_impls: DashMap::new(),
46 }
47 }
48
49 pub fn inner(&self) -> &DashMap<TypeId, CompRef> {
51 &self.inner
52 }
53
54 pub fn into_inner(self) -> DashMap<TypeId, CompRef> {
56 self.inner
57 }
58
59 pub fn insert_cached<T: Any + Send + Sync>(&self, value: T) {
61 self.inner
62 .insert(TypeId::of::<T>(), CompRef::Cached(Arc::new(value)));
63 }
64
65 pub fn insert_arc<T: Any + Send + Sync>(&self, arc: Arc<T>) {
67 self.inner
68 .insert(TypeId::of::<T>(), CompRef::Cached(arc as Arc<dyn Any + Send + Sync>));
69 }
70
71 pub fn insert_factory<T: Any + Send + Sync, F>(&self, factory: F)
76 where
77 F: Fn(&Store) -> Arc<T> + Send + Sync + 'static,
78 {
79 let type_id = TypeId::of::<T>();
80 self.inner.insert(type_id, CompRef::Factory(Arc::new(move |store| {
81 factory(store) as Arc<dyn Any + Send + Sync>
82 })));
83 }
84
85 pub fn inject<T: Component>(&self) -> Result<Arc<T>, AppError> {
94 let tid = TypeId::of::<T>();
95 let type_name = std::any::type_name::<T>();
96
97 match self.inner.get(&tid) {
98 Some(entry) => {
99 let any_arc = match &*entry {
100 CompRef::Cached(arc) => arc.clone(),
101 CompRef::Factory(f) => f(self),
102 };
103 any_arc.downcast::<T>().map_err(|bad_arc| {
104 let actual = (&*bad_arc).type_id();
105 AppError::with_context(
106 DiErr::InjectError,
107 format!(
108 "downcast 失败: 期望 `{}`, 实际 TypeId={:?}",
109 type_name, actual
110 ),
111 )
112 })
113 }
114 None => {
115 let count = self.inner.len();
116 Err(AppError::with_context(
117 DiErr::InjectError,
118 format!(
119 "组件 `{}` (TypeId={:?}) 未注册。\n\
120 请确认:\n\
121 1. 该结构体已标注 #[derive(Component)]\n\
122 2. 所在 crate 已在 Cargo.toml 中引入\n\
123 当前已注册 {} 个组件",
124 type_name, tid, count
125 ),
126 ))
127 }
128 }
129 }
130
131 pub fn inject_or_panic<T: Component>(&self) -> Arc<T> {
135 match self.inject::<T>() {
136 Ok(arc) => arc,
137 Err(e) => panic!("{}", e),
138 }
139 }
140
141 pub fn try_inject<T: Component>(&self) -> Option<Arc<T>> {
143 self.inject::<T>().ok()
144 }
145
146 pub fn contains<T: Any + Send + Sync>(&self) -> bool {
148 self.inner.contains_key(&TypeId::of::<T>())
149 }
150
151 pub fn len(&self) -> usize {
153 self.inner.len()
154 }
155
156 pub fn is_empty(&self) -> bool {
158 self.inner.is_empty()
159 }
160}
161
162impl Default for Store {
163 fn default() -> Self {
164 Self::new()
165 }
166}
167
168pub fn inject_from_store<T: Component>(store: &Store) -> Arc<T> {
178 store.inject_or_panic::<T>()
179}
180
181#[derive(Clone, Copy)]
185pub struct TraitImplEntry {
186 pub concrete_tid: fn() -> TypeId,
188 pub upcast: fn(Arc<dyn Any + Send + Sync>) -> Arc<dyn Any + Send + Sync>,
191}
192
193pub type TraitImplMap = DashMap<TypeId, Vec<TraitImplEntry>>;
195
196pub fn inject_trait_from_store<T: ?Sized + Any + Send + Sync + 'static>(
204 store: &Store,
205) -> Arc<T> {
206 let tid = TypeId::of::<T>();
207 let type_name = std::any::type_name::<T>();
208
209 store
210 .trait_impls
211 .get(&tid)
212 .and_then(|entries| entries.first().cloned())
213 .map(|entry| {
214 let concrete = store
215 .inner()
216 .get(&(entry.concrete_tid)())
217 .map(|r| match &*r {
218 CompRef::Cached(any_arc) => any_arc.clone(),
219 CompRef::Factory(f) => f(store),
220 })
221 .unwrap_or_else(|| {
222 panic!(
223 "[di] trait `{}` 的具体实现未注册到 store",
224 type_name
225 )
226 });
227 let trait_any = (entry.upcast)(concrete);
228 trait_any
229 .downcast_ref::<Arc<T>>()
230 .expect("[di] trait upcast 类型不匹配")
231 .clone()
232 })
233 .unwrap_or_else(|| {
234 panic!(
235 "[di] 注入失败: trait `{}` 无任何实现。\n\
236 请确认:\n\
237 1. 实现该 trait 的结构体已标注 #[component(as_trait = dyn Trait)]\n\
238 2. 所在 crate 已在 Cargo.toml 中引入",
239 type_name
240 )
241 })
242}
243
244pub fn inject_all_traits_from_store<T: ?Sized + Any + Send + Sync + 'static>(
246 store: &Store,
247) -> Vec<Arc<T>> {
248 let tid = TypeId::of::<T>();
249
250 store
251 .trait_impls
252 .get(&tid)
253 .map(|entries| {
254 entries
255 .iter()
256 .map(|entry| {
257 let concrete = store
258 .inner()
259 .get(&(entry.concrete_tid)())
260 .map(|r| match &*r {
261 CompRef::Cached(any_arc) => any_arc.clone(),
262 CompRef::Factory(f) => f(store),
263 })
264 .expect("[di] trait 具体实现未注册到 store");
265 let trait_any = (entry.upcast)(concrete);
266 trait_any
267 .downcast_ref::<Arc<T>>()
268 .expect("[di] trait upcast 类型不匹配")
269 .clone()
270 })
271 .collect()
272 })
273 .unwrap_or_default()
274}