ferroui_dependency_injection/
service_collection.rs1use crate::*;
6use std::rc::Rc;
7
8#[derive(Clone, Default)]
10pub struct ServiceCollection {
11 descriptors: Vec<ServiceDescriptor>,
12 read_only: bool,
13}
14pub trait IServiceCollection {
15 fn descriptors(&self) -> &[ServiceDescriptor];
16 fn add(&mut self, descriptor: ServiceDescriptor) -> &mut Self;
17}
18impl IServiceCollection for ServiceCollection {
19 fn descriptors(&self) -> &[ServiceDescriptor] {
20 &self.descriptors
21 }
22 fn add(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
23 self.add(descriptor)
24 }
25}
26impl ServiceCollection {
27 pub fn new() -> Self {
28 Self::default()
29 }
30 pub fn descriptors(&self) -> &[ServiceDescriptor] {
31 &self.descriptors
32 }
33 pub fn len(&self) -> usize {
34 self.descriptors.len()
35 }
36 pub fn is_empty(&self) -> bool {
37 self.descriptors.is_empty()
38 }
39 pub fn is_read_only(&self) -> bool {
40 self.read_only
41 }
42 pub fn make_read_only(&mut self) {
43 self.read_only = true;
44 }
45 fn ensure_mutable(&self) {
48 assert!(!self.read_only, "The service collection is read-only");
49 }
50 pub fn add(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
51 self.ensure_mutable();
52 self.descriptors.push(descriptor);
53 self
54 }
55 pub fn add_sequence(
56 &mut self,
57 descriptors: impl IntoIterator<Item = ServiceDescriptor>,
58 ) -> &mut Self {
59 self.ensure_mutable();
60 self.descriptors.extend(descriptors);
61 self
62 }
63 pub fn insert(&mut self, index: usize, descriptor: ServiceDescriptor) {
64 self.ensure_mutable();
65 self.descriptors.insert(index, descriptor);
66 }
67 pub fn remove_at(&mut self, index: usize) -> ServiceDescriptor {
68 self.ensure_mutable();
69 self.descriptors.remove(index)
70 }
71 pub fn clear(&mut self) {
72 self.ensure_mutable();
73 self.descriptors.clear();
74 }
75 pub fn try_add(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
76 self.ensure_mutable();
77 if !self
78 .descriptors
79 .iter()
80 .any(|d| d.identifier == descriptor.identifier)
81 {
82 self.add(descriptor);
83 }
84 self
85 }
86 pub fn try_add_enumerable(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
87 self.ensure_mutable();
88 let implementation = descriptor
89 .implementation_type
90 .expect("TryAddEnumerable needs with_implementation::<I>()");
91 assert!(
92 implementation != descriptor.service_type()
93 && implementation != ServiceType::of::<dyn std::any::Any>(),
94 "Implementation type is indistinguishable from the service type"
95 );
96 if !self.descriptors.iter().any(|d| {
97 d.identifier == descriptor.identifier && d.implementation_type == Some(implementation)
98 }) {
99 self.add(descriptor);
100 }
101 self
102 }
103 pub fn replace(&mut self, descriptor: ServiceDescriptor) -> &mut Self {
105 self.ensure_mutable();
106 if let Some(i) = self
107 .descriptors
108 .iter()
109 .position(|d| d.identifier == descriptor.identifier)
110 {
111 self.descriptors.remove(i);
112 }
113 self.add(descriptor)
114 }
115 pub fn remove_all<S: ?Sized + 'static>(&mut self) -> &mut Self {
116 self.remove_all_keyed::<S>(None)
117 }
118 pub fn remove_all_keyed<S: ?Sized + 'static>(&mut self, key: Option<ServiceKey>) -> &mut Self {
119 self.ensure_mutable();
120 let id = ServiceIdentifier::keyed::<S>(key);
121 self.descriptors.retain(|d| d.identifier != id);
122 self
123 }
124 pub fn iter(&self) -> std::slice::Iter<'_, ServiceDescriptor> {
125 self.descriptors.iter()
126 }
127 pub fn contains(&self, descriptor: &ServiceDescriptor) -> bool {
128 self.index_of(descriptor).is_some()
129 }
130 pub fn index_of(&self, descriptor: &ServiceDescriptor) -> Option<usize> {
131 self.descriptors
132 .iter()
133 .position(|d| Rc::ptr_eq(&d.identity, &descriptor.identity))
134 }
135 pub fn remove(&mut self, descriptor: &ServiceDescriptor) -> bool {
136 self.ensure_mutable();
137 if let Some(index) = self.index_of(descriptor) {
138 self.descriptors.remove(index);
139 true
140 } else {
141 false
142 }
143 }
144 pub fn copy_to(&self, target: &mut [ServiceDescriptor], index: usize) {
145 target[index..index + self.len()].clone_from_slice(&self.descriptors);
146 }
147 pub fn build_service_provider(
148 &self,
149 options: ServiceProviderOptions,
150 ) -> ServiceResult<ServiceProvider> {
151 ServiceProvider::build(self.descriptors.clone(), options)
152 }
153 pub fn add_singleton_instance<S: ?Sized + 'static>(&mut self, value: Rc<S>) -> &mut Self {
154 self.add(ServiceDescriptor::instance(value))
155 }
156 pub fn add_keyed_singleton_instance<S: ?Sized + 'static>(
157 &mut self,
158 key: Option<ServiceKey>,
159 value: Rc<S>,
160 ) -> &mut Self {
161 self.add(ServiceDescriptor::instance(value).with_key(key))
162 }
163}
164macro_rules! registrations {
165 ($add:ident, $keyed:ident, $lifetime:ident) => {
166 impl ServiceCollection {
167 pub fn $add<S: ?Sized + 'static, F>(&mut self, factory: F) -> &mut Self
168 where
169 F: Fn(&ServiceProvider) -> ServiceResult<Rc<S>> + 'static,
170 {
171 self.add(ServiceDescriptor::new(ServiceLifetime::$lifetime, factory))
172 }
173 pub fn $keyed<S: ?Sized + 'static, F>(
174 &mut self,
175 key: Option<ServiceKey>,
176 factory: F,
177 ) -> &mut Self
178 where
179 F: Fn(&ServiceProvider, Option<&ServiceKey>) -> ServiceResult<Rc<S>> + 'static,
180 {
181 self.add(ServiceDescriptor::keyed(
182 ServiceLifetime::$lifetime,
183 key,
184 factory,
185 ))
186 }
187 }
188 };
189}
190registrations!(add_singleton, add_keyed_singleton, Singleton);
191registrations!(add_scoped, add_keyed_scoped, Scoped);
192registrations!(add_transient, add_keyed_transient, Transient);
193
194impl std::ops::Index<usize> for ServiceCollection {
195 type Output = ServiceDescriptor;
196 fn index(&self, index: usize) -> &Self::Output {
197 &self.descriptors[index]
198 }
199}
200impl std::ops::IndexMut<usize> for ServiceCollection {
201 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
202 self.ensure_mutable();
203 &mut self.descriptors[index]
204 }
205}
206impl<'a> IntoIterator for &'a ServiceCollection {
207 type Item = &'a ServiceDescriptor;
208 type IntoIter = std::slice::Iter<'a, ServiceDescriptor>;
209 fn into_iter(self) -> Self::IntoIter {
210 self.iter()
211 }
212}