1use crate::{
2 Ref, ServiceCardinality::*, ServiceDependency, ServiceDescriptor, ServiceDescriptorBuilder, ServiceLifetime::*,
3 ServiceProvider, Type,
4};
5use std::any::Any;
6use std::mem::MaybeUninit;
7use std::sync::OnceLock;
8
9type Sdb<TSvc, TImpl> = ServiceDescriptorBuilder<TSvc, TImpl>;
10
11macro_rules! service_from_type {
12 ($($traits:tt)+) => {
13 #[inline(always)]
14 fn no_op(_: &ServiceProvider) -> Ref<dyn $($traits)+> {
15 Ref::new(MaybeUninit::<Box<dyn $($traits)+>>::uninit())
16 }
17
18 #[inline]
20 pub fn singleton<TSvc: ?Sized + $($traits)+, TImpl>() -> ServiceDescriptorBuilder<TSvc, TImpl> {
21 Sdb::new(Singleton, Type::of::<TImpl>())
22 }
23
24 #[inline]
26 pub fn singleton_with_key<TKey, TSvc: ?Sized + $($traits)+, TImpl>() -> ServiceDescriptorBuilder<TSvc, TImpl> {
27 Sdb::keyed::<TKey>(Singleton, Type::of::<TImpl>())
28 }
29
30 #[inline]
36 pub fn singleton_as_self<T: $($traits)+>() -> ServiceDescriptorBuilder<T, T> {
37 Sdb::new(Singleton, Type::of::<T>())
38 }
39
40 #[inline]
42 pub fn scoped<TSvc: ?Sized + $($traits)+, TImpl>() -> ServiceDescriptorBuilder<TSvc, TImpl> {
43 Sdb::new(Scoped, Type::of::<TImpl>())
44 }
45
46 #[inline]
48 pub fn scoped_with_key<TKey, TSvc: ?Sized + $($traits)+, TImpl>() -> ServiceDescriptorBuilder<TSvc, TImpl> {
49 Sdb::keyed::<TKey>(Scoped, Type::of::<TImpl>())
50 }
51
52 #[inline]
54 pub fn transient<TSvc: ?Sized + $($traits)+, TImpl>() -> ServiceDescriptorBuilder<TSvc, TImpl> {
55 Sdb::new(Transient, Type::of::<TImpl>())
56 }
57
58 #[inline]
60 pub fn transient_with_key<TKey, TSvc: ?Sized + $($traits)+, TImpl>() -> ServiceDescriptorBuilder<TSvc, TImpl> {
61 Sdb::keyed::<TKey>(Transient, Type::of::<TImpl>())
62 }
63
64 #[inline]
70 pub fn transient_as_self<T: $($traits)+>() -> ServiceDescriptorBuilder<T, T> {
71 Sdb::new(Transient, Type::of::<T>())
72 }
73
74 #[inline]
80 pub fn transient_with_key_as_self<TKey, TSvc: $($traits)+>() -> ServiceDescriptorBuilder<TSvc, TSvc> {
81 Sdb::keyed::<TKey>(Transient, Type::of::<TSvc>())
82 }
83
84 #[inline]
94 pub fn existing<TSvc: ?Sized + $($traits)+, TImpl>(instance: Box<TSvc>) -> ServiceDescriptor {
95 ServiceDescriptor::new(
96 Singleton,
97 Type::of::<TSvc>(),
98 Type::of::<TImpl>(),
99 Vec::new(),
100 OnceLock::from(Ref::new(Ref::<TSvc>::from(instance)) as Ref<dyn $($traits)+>),
101 Ref::new(no_op),
102 )
103 }
104
105 #[inline]
115 pub fn existing_as_self<T: $($traits)+>(instance: T) -> ServiceDescriptor {
116 ServiceDescriptor::new(
117 Singleton,
118 Type::of::<T>(),
119 Type::of::<T>(),
120 Vec::new(),
121 OnceLock::from(Ref::new(Ref::from(instance)) as Ref<dyn $($traits)+>),
122 Ref::new(no_op),
123 )
124 }
125
126 #[inline]
136 pub fn existing_with_key<TKey, TSvc: ?Sized + $($traits)+, TImpl>(instance: Box<TSvc>) -> ServiceDescriptor {
137 ServiceDescriptor::new(
138 Singleton,
139 Type::keyed::<TKey, TSvc>(),
140 Type::of::<TImpl>(),
141 Vec::new(),
142 OnceLock::from(Ref::new(Ref::<TSvc>::from(instance)) as Ref<dyn $($traits)+>),
143 Ref::new(no_op),
144 )
145 }
146
147 #[inline]
157 pub fn existing_with_key_as_self<TKey, TSvc: $($traits)+>(instance: TSvc) -> ServiceDescriptor {
158 ServiceDescriptor::new(
159 Singleton,
160 Type::keyed::<TKey, TSvc>(),
161 Type::of::<TSvc>(),
162 Vec::new(),
163 OnceLock::from(Ref::new(Ref::from(instance)) as Ref<dyn $($traits)+>),
164 Ref::new(no_op),
165 )
166 }
167 };
168}
169
170macro_rules! service_from_func {
171 (($($traits:tt)+), ($($bounds:tt)+)) => {
172 #[inline]
178 pub fn singleton_factory<T: ?Sized + $($traits)+, F>(factory: F) -> ServiceDescriptor
179 where
180 F: Fn(&ServiceProvider) -> Ref<T> + $($bounds)+,
181 {
182 Sdb::<T, ()>::new(Singleton, Type::factory_of::<T>()).from(factory)
183 }
184
185 #[inline]
191 pub fn singleton_with_key_factory<TKey, TSvc: ?Sized + $($traits)+, F>(factory: F) -> ServiceDescriptor
192 where
193 F: Fn(&ServiceProvider) -> Ref<TSvc> + $($bounds)+,
194 {
195 Sdb::<TSvc, ()>::keyed::<TKey>(Singleton, Type::factory_of::<TSvc>()).from(factory)
196 }
197
198 #[inline]
204 pub fn scoped_factory<T: ?Sized + $($traits)+, F>(factory: F) -> ServiceDescriptor
205 where
206 F: Fn(&ServiceProvider) -> Ref<T> + $($bounds)+,
207 {
208 Sdb::<T, ()>::new(Scoped, Type::factory_of::<T>()).from(factory)
209 }
210
211 #[inline]
217 pub fn scoped_with_key_factory<TKey, TSvc: ?Sized + $($traits)+, F>(factory: F) -> ServiceDescriptor
218 where
219 F: Fn(&ServiceProvider) -> Ref<TSvc> + $($bounds)+,
220 {
221 Sdb::<TSvc, ()>::keyed::<TKey>(Scoped, Type::factory_of::<TSvc>()).from(factory)
222 }
223
224 #[inline]
230 pub fn transient_factory<T: ?Sized + $($traits)+, F>(factory: F) -> ServiceDescriptor
231 where
232 F: Fn(&ServiceProvider) -> Ref<T> + $($bounds)+,
233 {
234 Sdb::<T, ()>::new(Transient, Type::factory_of::<T>()).from(factory)
235 }
236
237 #[inline]
243 pub fn transient_with_key_factory<TKey, TSvc: ?Sized + $($traits)+, F>(factory: F) -> ServiceDescriptor
244 where
245 F: Fn(&ServiceProvider) -> Ref<TSvc> + $($bounds)+,
246 {
247 Sdb::<TSvc, ()>::keyed::<TKey>(Transient, Type::factory_of::<TSvc>()).from(factory)
248 }
249 };
250}
251
252cfg_if::cfg_if! {
253 if #[cfg(feature = "async")] {
254 service_from_type!(Any + Send + Sync);
255 service_from_func!((Any + Send + Sync), (Send + Sync + 'static));
256 } else {
257 service_from_type!(Any);
258 service_from_func!((Any), ('static));
259 }
260}
261
262#[inline]
264pub fn exactly_one<T: Any + ?Sized>() -> ServiceDependency {
265 ServiceDependency::new(Type::of::<T>(), ExactlyOne)
266}
267
268#[inline]
270pub fn exactly_one_with_key<TKey, TSvc: Any + ?Sized>() -> ServiceDependency {
271 ServiceDependency::new(Type::keyed::<TKey, TSvc>(), ExactlyOne)
272}
273
274#[inline]
276pub fn zero_or_one<T: Any + ?Sized>() -> ServiceDependency {
277 ServiceDependency::new(Type::of::<T>(), ZeroOrOne)
278}
279
280#[inline]
282pub fn zero_or_one_with_key<TKey, TSvc: Any + ?Sized>() -> ServiceDependency {
283 ServiceDependency::new(Type::keyed::<TKey, TSvc>(), ZeroOrOne)
284}
285
286#[inline]
288pub fn zero_or_more<T: Any + ?Sized>() -> ServiceDependency {
289 ServiceDependency::new(Type::of::<T>(), ZeroOrMore)
290}
291
292#[inline]
294pub fn zero_or_more_with_key<TKey, TSvc: Any + ?Sized>() -> ServiceDependency {
295 ServiceDependency::new(Type::keyed::<TKey, TSvc>(), ZeroOrMore)
296}