ferroui_dependency_injection/
service_descriptor.rs1use crate::*;
4use ferroui_system::{threading::tasks::Task, IDisposable};
5use std::rc::Rc;
6
7pub trait IAsyncDisposable {
9 fn dispose_async(&self) -> Task<()>;
10}
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub enum ServiceKeyLookupMode {
14 NullKey,
15 ExplicitKey,
16 InheritKey,
17}
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19pub enum DependencyKind {
20 Required,
21 Optional,
22 Enumerable,
23}
24
25#[derive(Clone, Debug)]
27pub struct Dependency {
28 pub identifier: ServiceIdentifier,
29 pub kind: DependencyKind,
30 pub lookup_mode: ServiceKeyLookupMode,
31}
32impl Dependency {
33 pub fn required<S: ?Sized + 'static>() -> Self {
34 Self {
35 identifier: ServiceIdentifier::of::<S>(),
36 kind: DependencyKind::Required,
37 lookup_mode: ServiceKeyLookupMode::NullKey,
38 }
39 }
40 pub fn keyed<S: ?Sized + 'static>(key: Option<ServiceKey>) -> Self {
41 Self {
42 lookup_mode: if key.is_some() {
43 ServiceKeyLookupMode::ExplicitKey
44 } else {
45 ServiceKeyLookupMode::NullKey
46 },
47 identifier: ServiceIdentifier::keyed::<S>(key),
48 kind: DependencyKind::Required,
49 }
50 }
51 pub fn inherited<S: ?Sized + 'static>() -> Self {
52 Self {
53 lookup_mode: ServiceKeyLookupMode::InheritKey,
54 ..Self::required::<S>()
55 }
56 }
57 pub fn optional(mut self) -> Self {
58 self.kind = DependencyKind::Optional;
59 self
60 }
61 pub fn enumerable(mut self) -> Self {
62 self.kind = DependencyKind::Enumerable;
63 self
64 }
65 pub(crate) fn identifier_for(&self, key: &Option<ServiceKey>) -> ServiceIdentifier {
66 let mut id = self.identifier.clone();
67 if self.lookup_mode == ServiceKeyLookupMode::InheritKey {
68 id.service_key = key.clone();
69 }
70 id
71 }
72}
73
74pub type ErasedFactory =
75 Rc<dyn Fn(&ServiceProvider, Option<&ServiceKey>) -> ServiceResult<ErasedService>>;
76pub(crate) type Enumerate = fn(&ErasedService) -> Vec<ErasedService>;
77pub(crate) type Dispose = Rc<dyn Fn(&ErasedService)>;
78pub(crate) type DisposeAsync = Rc<dyn Fn(&ErasedService) -> Task<()>>;
79
80#[derive(Clone)]
83pub struct ServiceDescriptor {
84 pub(crate) identity: Rc<()>,
85 pub(crate) enumerable: Option<(ServiceType, Enumerate)>,
86 instance_value: Option<ErasedService>,
87 pub(crate) identifier: ServiceIdentifier,
88 pub(crate) lifetime: ServiceLifetime,
89 pub(crate) factory: ErasedFactory,
90 pub(crate) dependencies: Vec<Dependency>,
91 pub(crate) implementation_type: Option<ServiceType>,
92 pub(crate) dispose: Option<Dispose>,
93 pub(crate) dispose_async: Option<DisposeAsync>,
94 pub(crate) instance: bool,
95}
96impl ServiceDescriptor {
97 pub fn new<S: ?Sized + 'static, F>(lifetime: ServiceLifetime, factory: F) -> Self
98 where
99 F: Fn(&ServiceProvider) -> ServiceResult<Rc<S>> + 'static,
100 {
101 Self::keyed::<S, _>(lifetime, None, move |p, _| factory(p))
102 }
103 pub fn keyed<S: ?Sized + 'static, F>(
104 lifetime: ServiceLifetime,
105 key: Option<ServiceKey>,
106 factory: F,
107 ) -> Self
108 where
109 F: Fn(&ServiceProvider, Option<&ServiceKey>) -> ServiceResult<Rc<S>> + 'static,
110 {
111 Self::from_erased(ServiceIdentifier::keyed::<S>(key), lifetime, move |p, k| {
112 factory(p, k).map(erase_service)
113 })
114 }
115 pub fn from_erased(
116 identifier: ServiceIdentifier,
117 lifetime: ServiceLifetime,
118 factory: impl Fn(&ServiceProvider, Option<&ServiceKey>) -> ServiceResult<ErasedService>
119 + 'static,
120 ) -> Self {
121 Self {
122 identity: Rc::new(()),
123 enumerable: None,
124 instance_value: None,
125 identifier,
126 lifetime,
127 factory: Rc::new(factory),
128 dependencies: Vec::new(),
129 implementation_type: None,
130 dispose: None,
131 dispose_async: None,
132 instance: false,
133 }
134 }
135 pub fn instance<S: ?Sized + 'static>(value: Rc<S>) -> Self {
136 let instance = erase_service(value.clone());
137 let mut descriptor = Self::new(ServiceLifetime::Singleton, move |_| Ok(value.clone()));
138 descriptor.instance_value = Some(instance);
139 descriptor.instance = true;
140 descriptor
141 }
142 pub fn enumerable_instance<S: ?Sized + 'static>(values: Vec<Rc<S>>) -> Self {
144 let mut descriptor = Self::instance(Rc::new(values));
145 descriptor.enumerable = Some((ServiceType::of::<S>(), |value| {
146 unerase_service::<Vec<Rc<S>>>(value)
147 .expect("typed enumerable")
148 .iter()
149 .cloned()
150 .map(erase_service)
151 .collect()
152 }));
153 descriptor
154 }
155 pub fn from_factory<S: ?Sized + 'static>(
156 lifetime: ServiceLifetime,
157 factory: ObjectFactory<S>,
158 ) -> Self {
159 let mut descriptor = Self::keyed(lifetime, None, move |p, k| (factory.factory)(p, k));
160 descriptor.dependencies = factory.dependencies;
161 descriptor
162 }
163 pub fn with_key(mut self, key: Option<ServiceKey>) -> Self {
164 self.identifier.service_key = key;
165 self
166 }
167 pub fn with_dependencies(mut self, dependencies: Vec<Dependency>) -> Self {
168 self.dependencies = dependencies;
169 self
170 }
171 pub fn with_implementation<I: ?Sized + 'static>(mut self) -> Self {
173 self.implementation_type = Some(ServiceType::of::<I>());
174 self
175 }
176 pub fn with_disposal<S: ?Sized + IDisposable + 'static>(self) -> Self {
177 self.on_dispose::<S>(|value| value.dispose())
178 }
179 pub fn with_async_disposal<S: ?Sized + IAsyncDisposable + 'static>(self) -> Self {
180 self.on_dispose_async::<S>(|value| value.dispose_async())
181 }
182 pub fn on_dispose<S: ?Sized + 'static>(mut self, dispose: impl Fn(&S) + 'static) -> Self {
183 assert_eq!(
184 self.service_type(),
185 ServiceType::of::<S>(),
186 "disposer must match service type"
187 );
188 assert!(
189 !self.instance,
190 "externally supplied instances are not owned by the provider"
191 );
192 self.dispose = Some(Rc::new(move |v| {
193 dispose(&*unerase_service::<S>(v).expect("typed factory"))
194 }));
195 self
196 }
197 pub fn on_dispose_async<S: ?Sized + 'static>(
198 mut self,
199 dispose: impl Fn(Rc<S>) -> Task<()> + 'static,
200 ) -> Self {
201 assert_eq!(
202 self.service_type(),
203 ServiceType::of::<S>(),
204 "disposer must match service type"
205 );
206 assert!(
207 !self.instance,
208 "externally supplied instances are not owned by the provider"
209 );
210 self.dispose_async = Some(Rc::new(move |v| {
211 dispose(unerase_service::<S>(v).expect("typed factory"))
212 }));
213 self
214 }
215 pub fn implementation_type(&self) -> Option<ServiceType> {
216 self.implementation_type
217 }
218 pub fn implementation_instance(&self) -> Option<ErasedService> {
219 self.instance_value.clone()
220 }
221 pub fn implementation_factory(&self) -> Option<crate::service_descriptor::ErasedFactory> {
222 if self.instance {
223 None
224 } else {
225 Some(self.factory.clone())
226 }
227 }
228 pub fn service_type(&self) -> ServiceType {
229 self.identifier.service_type
230 }
231 pub fn service_key(&self) -> Option<&ServiceKey> {
232 self.identifier.service_key.as_ref()
233 }
234 pub fn lifetime(&self) -> ServiceLifetime {
235 self.lifetime
236 }
237 pub fn is_keyed_service(&self) -> bool {
238 self.service_key().is_some()
239 }
240 pub fn dependencies(&self) -> &[Dependency] {
241 &self.dependencies
242 }
243}
244
245impl std::fmt::Debug for ServiceDescriptor {
246 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247 f.debug_struct("ServiceDescriptor")
248 .field("identifier", &self.identifier)
249 .field("lifetime", &self.lifetime)
250 .field("implementation_type", &self.implementation_type)
251 .field("instance", &self.instance)
252 .finish()
253 }
254}
255impl std::fmt::Display for ServiceDescriptor {
256 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
257 write!(f, "{self:?}")
258 }
259}