1use crate::{Mut, ServiceDependency, ServiceProvider, Type};
2use spin::Once;
3use std::any::Any;
4
5#[derive(Copy, Clone, Debug, PartialEq)]
7pub enum ServiceLifetime {
8 Singleton,
10
11 Scoped,
13
14 Transient,
16}
17
18#[cfg(not(feature = "async"))]
20pub type Ref<T> = std::rc::Rc<T>;
21
22#[cfg(feature = "async")]
24pub type Ref<T> = std::sync::Arc<T>;
25
26pub type RefMut<T> = Ref<Mut<T>>;
28
29pub type ServiceFactory = dyn Fn(&ServiceProvider) -> Ref<dyn Any>;
31
32pub struct ServiceDescriptor {
34 lifetime: ServiceLifetime,
35 service_type: Type,
36 implementation_type: Type,
37 dependencies: Vec<ServiceDependency>,
38 instance: Ref<Once<Ref<dyn Any>>>,
39 factory: Ref<ServiceFactory>,
40}
41
42impl ServiceDescriptor {
43 #[cfg(any(feature = "builder", feature = "inject"))]
44 pub(crate) fn new(
45 lifetime: ServiceLifetime,
46 service_type: Type,
47 implementation_type: Type,
48 dependencies: Vec<ServiceDependency>,
49 instance: Once<Ref<dyn Any>>,
50 factory: Ref<ServiceFactory>,
51 ) -> Self {
52 Self {
53 lifetime,
54 service_type,
55 implementation_type,
56 dependencies,
57 instance: Ref::new(instance),
58 factory,
59 }
60 }
61
62 pub fn lifetime(&self) -> ServiceLifetime {
64 self.lifetime
65 }
66
67 pub fn service_type(&self) -> &Type {
69 &self.service_type
70 }
71
72 pub fn implementation_type(&self) -> &Type {
74 &self.implementation_type
75 }
76
77 pub fn dependencies(&self) -> &[ServiceDependency] {
79 &self.dependencies
80 }
81
82 pub fn get(&self, services: &ServiceProvider) -> Ref<dyn Any> {
88 if self.lifetime == ServiceLifetime::Transient {
89 return (self.factory)(services);
90 }
91
92 return self.instance.call_once(|| (self.factory)(services)).clone();
93 }
94
95 pub(crate) fn clone_with(&self, dependencies: bool) -> Self {
96 Self {
97 lifetime: self.lifetime,
98 service_type: self.service_type.clone(),
99 implementation_type: self.implementation_type.clone(),
100 dependencies: if dependencies {
101 self.dependencies.clone()
102 } else {
103 Vec::with_capacity(0)
104 },
105 instance: if self.lifetime == ServiceLifetime::Singleton {
106 self.instance.clone()
107 } else {
108 Ref::new(Once::new())
109 },
110 factory: self.factory.clone(),
111 }
112 }
113}
114
115impl Clone for ServiceDescriptor {
116 fn clone(&self) -> Self {
117 self.clone_with(true)
120 }
121}