di/
descriptor.rs

1use crate::{Mut, ServiceDependency, ServiceProvider, Type};
2use spin::Once;
3use std::any::Any;
4
5/// Represents the possible service lifetimes.
6#[derive(Copy, Clone, Debug, PartialEq)]
7pub enum ServiceLifetime {
8    /// Indicates that a single instance of the service will be created.
9    Singleton,
10
11    /// Indicates that a new instance of the service will be created for each scope.
12    Scoped,
13
14    /// Indicates that a new instance of the service will be created every time it is requested.
15    Transient,
16}
17
18/// Represents the type alias for a service reference.
19#[cfg(not(feature = "async"))]
20pub type Ref<T> = std::rc::Rc<T>;
21
22/// Represents the type alias for a service reference.
23#[cfg(feature = "async")]
24pub type Ref<T> = std::sync::Arc<T>;
25
26/// Represents the type alias for a mutable service reference.
27pub type RefMut<T> = Ref<Mut<T>>;
28
29/// Represents the callback function used to create a service.
30pub type ServiceFactory = dyn Fn(&ServiceProvider) -> Ref<dyn Any>;
31
32/// Represents the description of a service with its service type, implementation, and lifetime.
33pub 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    /// Gets the [lifetime](crate::ServiceLifetime) associated with the service descriptor.
63    pub fn lifetime(&self) -> ServiceLifetime {
64        self.lifetime
65    }
66
67    /// Gets the service [type](crate::Type) associated with the service descriptor.
68    pub fn service_type(&self) -> &Type {
69        &self.service_type
70    }
71
72    /// Gets the implementation [type](crate::Type) associated with the service descriptor.
73    pub fn implementation_type(&self) -> &Type {
74        &self.implementation_type
75    }
76
77    /// Gets the associated [service dependencies](crate::ServiceDependency), if any.
78    pub fn dependencies(&self) -> &[ServiceDependency] {
79        &self.dependencies
80    }
81
82    /// Gets or creates the service defined by the service descriptor.
83    ///
84    /// # Arguments
85    ///
86    /// * `services` - The current [`ServiceProvider`](crate::ServiceProvider)
87    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        // without context, we don't know if this is 'safe';
118        // always copy dependencies here
119        self.clone_with(true)
120    }
121}