1use std::any::{Any, TypeId};
2use std::sync::{Arc, Mutex};
3
4use crate::*;
5
6pub trait Builder: Send + Sync {
12 fn instance_type_id(&self) -> TypeId;
14
15 fn instance_type_name(&self) -> &'static str;
18
19 fn interfaces(&self, clb: &mut dyn FnMut(&InterfaceDesc) -> bool);
23
24 fn metadata<'a>(&'a self, clb: &mut dyn FnMut(&'a dyn std::any::Any) -> bool);
28
29 fn get_any(&self, cat: &Catalog) -> Result<Arc<dyn Any + Send + Sync>, InjectionError>;
31
32 fn check(&self, cat: &Catalog) -> Result<(), ValidationError>;
34}
35
36pub trait BuilderExt {
39 fn interfaces_get_all(&self) -> Vec<InterfaceDesc>;
40 fn interfaces_contain<Iface: 'static>(&self) -> bool;
41 fn interfaces_contain_type_id(&self, type_id: &TypeId) -> bool;
42
43 fn metadata_get_first<Meta: 'static>(&self) -> Option<&Meta>;
44 fn metadata_find_first<Meta: 'static>(&self, pred: impl Fn(&Meta) -> bool) -> Option<&Meta>;
45 fn metadata_get_all<Meta: 'static>(&self) -> Vec<&Meta>;
46 fn metadata_find_all<Meta: 'static>(&self, pred: impl Fn(&Meta) -> bool) -> Vec<&Meta>;
47 fn metadata_contains<Meta: 'static>(&self, pred: impl Fn(&Meta) -> bool) -> bool;
48}
49
50impl<T: Builder + ?Sized> BuilderExt for T {
51 fn interfaces_get_all(&self) -> Vec<InterfaceDesc> {
52 let mut ret = Vec::new();
53 self.interfaces(&mut |i| {
54 ret.push(*i);
55 true
56 });
57 ret
58 }
59
60 fn interfaces_contain<Iface: 'static>(&self) -> bool {
61 let type_id = TypeId::of::<Iface>();
62 self.interfaces_contain_type_id(&type_id)
63 }
64
65 fn interfaces_contain_type_id(&self, type_id: &TypeId) -> bool {
66 let mut ret = false;
67 self.interfaces(&mut |i| {
68 if i.type_id == *type_id {
69 ret = true;
70 return false;
71 }
72 true
73 });
74 ret
75 }
76
77 fn metadata_get_first<Meta: 'static>(&self) -> Option<&Meta> {
78 let mut ret: Option<&Meta> = None;
79 self.metadata(&mut |m| {
80 if let Some(v) = m.downcast_ref::<Meta>() {
81 ret = Some(v);
82 return false;
83 }
84 true
85 });
86 ret
87 }
88
89 fn metadata_find_first<Meta: 'static>(&self, pred: impl Fn(&Meta) -> bool) -> Option<&Meta> {
90 let mut ret: Option<&Meta> = None;
91 self.metadata(&mut |m| {
92 if let Some(v) = m.downcast_ref::<Meta>() {
93 if pred(v) {
94 ret = Some(v);
95 return false;
96 }
97 }
98 true
99 });
100 ret
101 }
102
103 fn metadata_get_all<Meta: 'static>(&self) -> Vec<&Meta> {
104 let mut ret: Vec<&Meta> = Vec::new();
105 self.metadata(&mut |m| {
106 if let Some(v) = m.downcast_ref::<Meta>() {
107 ret.push(v);
108 }
109 true
110 });
111 ret
112 }
113
114 fn metadata_find_all<Meta: 'static>(&self, pred: impl Fn(&Meta) -> bool) -> Vec<&Meta> {
115 let mut ret: Vec<&Meta> = Vec::new();
116 self.metadata(&mut |m| {
117 if let Some(v) = m.downcast_ref::<Meta>() {
118 if pred(v) {
119 ret.push(v);
120 }
121 }
122 true
123 });
124 ret
125 }
126
127 fn metadata_contains<Meta: 'static>(&self, pred: impl Fn(&Meta) -> bool) -> bool {
128 let mut ret = false;
129 self.metadata(&mut |m| {
130 if let Some(v) = m.downcast_ref::<Meta>() {
131 if pred(v) {
132 ret = true;
133 return false;
134 }
135 }
136 true
137 });
138 ret
139 }
140}
141
142pub trait TypedBuilder<T: Send + Sync + ?Sized>: Builder {
145 fn get(&self, cat: &Catalog) -> Result<Arc<T>, InjectionError>;
148
149 fn bind_interfaces(&self, cat: &mut CatalogBuilder);
152}
153
154pub trait TypedBuilderExt<T: Send + Sync + ?Sized>: TypedBuilder<T> {
155 fn without_default_interfaces(self) -> impl TypedBuilder<T>;
158}
159
160pub trait TypedBuilderCast<I: Send + Sync + ?Sized> {
161 fn cast(self) -> impl TypedBuilder<I>;
162}
163
164pub trait Component {
166 type Impl: Send + Sync;
167 type Builder: TypedBuilder<Self::Impl>;
168
169 fn builder() -> Self::Builder;
170}
171
172#[derive(Debug, Copy, Clone)]
173pub struct InterfaceDesc {
174 pub type_id: TypeId,
175 pub type_name: &'static str,
176}
177
178impl<Bld, Impl> TypedBuilderExt<Impl> for Bld
181where
182 Impl: Send + Sync,
183 Bld: TypedBuilder<Impl>,
184{
185 fn without_default_interfaces(self) -> impl TypedBuilder<Impl> {
186 TypedBuilderWithoudDefaultInterfaces(self)
187 }
188}
189
190pub struct TypedBuilderWithoudDefaultInterfaces<Bld>(Bld);
192
193impl<Bld> Builder for TypedBuilderWithoudDefaultInterfaces<Bld>
194where
195 Bld: Builder,
196{
197 fn instance_type_id(&self) -> TypeId {
198 self.0.instance_type_id()
199 }
200
201 fn instance_type_name(&self) -> &'static str {
202 self.0.instance_type_name()
203 }
204
205 fn interfaces(&self, clb: &mut dyn FnMut(&InterfaceDesc) -> bool) {
206 self.0.interfaces(clb);
207 }
208
209 fn metadata<'a>(&'a self, clb: &mut dyn FnMut(&'a dyn std::any::Any) -> bool) {
210 self.0.metadata(clb);
211 }
212
213 fn get_any(&self, cat: &Catalog) -> Result<Arc<dyn Any + Send + Sync>, InjectionError> {
214 self.0.get_any(cat)
215 }
216
217 fn check(&self, cat: &Catalog) -> Result<(), ValidationError> {
218 self.0.check(cat)
219 }
220}
221
222impl<Bld, Impl> TypedBuilder<Impl> for TypedBuilderWithoudDefaultInterfaces<Bld>
223where
224 Impl: Send + Sync,
225 Bld: TypedBuilder<Impl>,
226{
227 fn get(&self, cat: &Catalog) -> Result<Arc<Impl>, InjectionError> {
228 self.0.get(cat)
229 }
230
231 fn bind_interfaces(&self, _cat: &mut CatalogBuilder) {}
232}
233
234impl<Impl> Builder for Arc<Impl>
238where
239 Impl: Send + Sync + 'static,
240{
241 fn instance_type_id(&self) -> TypeId {
242 TypeId::of::<Impl>()
243 }
244
245 fn instance_type_name(&self) -> &'static str {
246 std::any::type_name::<Impl>()
247 }
248
249 fn interfaces(&self, _clb: &mut dyn FnMut(&InterfaceDesc) -> bool) {}
250
251 fn metadata<'a>(&'a self, _clb: &mut dyn FnMut(&'a dyn Any) -> bool) {}
252
253 fn get_any(&self, _cat: &Catalog) -> Result<Arc<dyn Any + Send + Sync>, InjectionError> {
254 Ok(self.clone())
255 }
256
257 fn check(&self, _cat: &Catalog) -> Result<(), ValidationError> {
258 Ok(())
259 }
260}
261
262impl<Impl> TypedBuilder<Impl> for Arc<Impl>
263where
264 Impl: Send + Sync + 'static,
265{
266 fn get(&self, _cat: &Catalog) -> Result<Arc<Impl>, InjectionError> {
267 Ok(self.clone())
268 }
269
270 fn bind_interfaces(&self, _cat: &mut CatalogBuilder) {}
271}
272
273impl<Fct, Impl> Builder for Fct
277where
278 Fct: Fn() -> Arc<Impl> + Send + Sync,
279 Impl: Send + Sync + 'static,
280{
281 fn instance_type_id(&self) -> TypeId {
282 TypeId::of::<Impl>()
283 }
284
285 fn instance_type_name(&self) -> &'static str {
286 std::any::type_name::<Impl>()
287 }
288
289 fn interfaces(&self, _clb: &mut dyn FnMut(&InterfaceDesc) -> bool) {}
290
291 fn metadata<'a>(&'a self, _clb: &mut dyn FnMut(&'a dyn Any) -> bool) {}
292
293 fn get_any(&self, _cat: &Catalog) -> Result<Arc<dyn Any + Send + Sync>, InjectionError> {
294 Ok(self())
295 }
296
297 fn check(&self, _cat: &Catalog) -> Result<(), ValidationError> {
298 Ok(())
299 }
300}
301
302impl<Fct, Impl> TypedBuilder<Impl> for Fct
303where
304 Fct: Fn() -> Arc<Impl> + Send + Sync,
305 Impl: Send + Sync + 'static,
306{
307 fn get(&self, _cat: &Catalog) -> Result<Arc<Impl>, InjectionError> {
308 Ok(self())
309 }
310
311 fn bind_interfaces(&self, _cat: &mut CatalogBuilder) {}
312}
313
314pub(crate) struct LazyBuilder<Fct, Impl>
317where
318 Fct: FnOnce() -> Impl,
319 Impl: 'static + Send + Sync,
320{
321 state: Mutex<LazyBuilderState<Fct, Impl>>,
322}
323
324struct LazyBuilderState<Fct, Impl> {
325 factory: Option<Fct>,
326 instance: Option<Arc<Impl>>,
327}
328
329impl<Fct, Impl> LazyBuilder<Fct, Impl>
330where
331 Fct: FnOnce() -> Impl,
332 Impl: 'static + Send + Sync,
333{
334 pub fn new(factory: Fct) -> Self {
335 Self {
336 state: Mutex::new(LazyBuilderState {
337 factory: Some(factory),
338 instance: None,
339 }),
340 }
341 }
342}
343
344impl<Fct, Impl> Builder for LazyBuilder<Fct, Impl>
345where
346 Fct: FnOnce() -> Impl + Send + Sync,
347 Impl: 'static + Send + Sync,
348{
349 fn instance_type_id(&self) -> TypeId {
350 TypeId::of::<Impl>()
351 }
352
353 fn instance_type_name(&self) -> &'static str {
354 std::any::type_name::<Impl>()
355 }
356
357 fn interfaces(&self, _clb: &mut dyn FnMut(&InterfaceDesc) -> bool) {}
358
359 fn metadata<'a>(&'a self, _clb: &mut dyn FnMut(&'a dyn Any) -> bool) {}
360
361 fn get_any(&self, cat: &Catalog) -> Result<Arc<dyn Any + Send + Sync>, InjectionError> {
362 Ok(TypedBuilder::get(self, cat)?)
363 }
364
365 fn check(&self, _cat: &Catalog) -> Result<(), ValidationError> {
366 Ok(())
367 }
368}
369
370impl<Fct, Impl> TypedBuilder<Impl> for LazyBuilder<Fct, Impl>
371where
372 Fct: FnOnce() -> Impl + Send + Sync,
373 Impl: 'static + Send + Sync,
374{
375 fn get(&self, _cat: &Catalog) -> Result<Arc<Impl>, InjectionError> {
376 let mut s = self.state.lock().unwrap();
377 if let Some(inst) = s.instance.as_ref() {
378 Ok(inst.clone())
379 } else {
380 let factory = s.factory.take().unwrap();
381 let inst = Arc::new(factory());
382 s.instance = Some(inst.clone());
383 Ok(inst)
384 }
385 }
386
387 fn bind_interfaces(&self, _cat: &mut CatalogBuilder) {}
388}