di/description/
builder.rs1use super::{ServiceDescriptor, ServiceLifetime};
2use crate::{Ref, ServiceDependency, ServiceProvider, Type};
3use std::any::Any;
4use std::marker::PhantomData;
5use std::sync::OnceLock;
6
7pub struct ServiceDescriptorBuilder<TSvc: ?Sized, TImpl> {
9 lifetime: ServiceLifetime,
10 service_type: Type,
11 implementation_type: Type,
12 dependencies: Vec<ServiceDependency>,
13 _marker_svc: PhantomData<TSvc>,
14 _marker_impl: PhantomData<TImpl>,
15}
16
17impl<TSvc: ?Sized, TImpl> ServiceDescriptorBuilder<TSvc, TImpl> {
18 pub fn depends_on(mut self, dependency: ServiceDependency) -> Self {
24 if !self.dependencies.contains(&dependency) {
25 self.dependencies.push(dependency);
26 }
27 self
28 }
29
30 pub fn new(lifetime: ServiceLifetime, implementation_type: Type) -> Self {
37 Self {
38 lifetime,
39 service_type: Type::of::<TSvc>(),
40 implementation_type,
41 dependencies: Vec::new(),
42 _marker_svc: PhantomData,
43 _marker_impl: PhantomData,
44 }
45 }
46
47 pub fn keyed<TKey>(lifetime: ServiceLifetime, implementation_type: Type) -> Self {
54 Self {
55 lifetime,
56 service_type: Type::keyed::<TKey, TSvc>(),
57 implementation_type,
58 dependencies: Vec::new(),
59 _marker_svc: PhantomData,
60 _marker_impl: PhantomData,
61 }
62 }
63}
64
65macro_rules! from {
66 (($($traits:tt)+), ($($bounds:tt)+)) => {
67 impl<TSvc: ?Sized + $($traits)+, TImpl> ServiceDescriptorBuilder<TSvc, TImpl> {
68 pub fn from(mut self, factory: impl (Fn(&ServiceProvider) -> Ref<TSvc>) + $($bounds)+) -> ServiceDescriptor {
74 ServiceDescriptor::new(
75 self.lifetime,
76 self.service_type,
77 self.implementation_type,
78 if self.dependencies.is_empty() {
79 Vec::new()
80 } else {
81 self.dependencies.shrink_to_fit();
82 self.dependencies
83 },
84 OnceLock::new(),
85 Ref::new(move |sp| Ref::new(factory(sp))),
86 )
87 }
88 }
89 }
90}
91
92cfg_if::cfg_if! {
93 if #[cfg(feature = "async")] {
94 from!((Any + Send + Sync), (Send + Sync + 'static));
95 } else {
96 from!((Any), ('static));
97 }
98}