1use super::cache::{new_provider_cache, ProviderCache, ProviderCacheKey};
2use super::entry::ProviderEntry;
3use super::provider_ref::ProviderRef;
4use super::resolution::{
5 enter_resolution_stack, new_resolution_stack, resolution_stack_is_empty,
6 ProviderResolutionStack,
7};
8use super::{
9 AnyProvider, ContextId, ContextIdFactory, FromModuleRef, ProviderDefinition, ProviderScope,
10 ProviderToken,
11};
12use crate::{BootError, BoxFuture, Result};
13use std::collections::{BTreeMap, BTreeSet};
14use std::fmt;
15use std::sync::{Arc, RwLock};
16
17#[derive(Clone, Default)]
19pub struct ModuleRef {
20 providers: Arc<RwLock<BTreeMap<ProviderToken, ProviderEntry>>>,
21 provider_order: Arc<RwLock<Vec<ProviderToken>>>,
22 visible_scopes: Arc<RwLock<Vec<ModuleRef>>>,
23 context_id: Option<ContextId>,
24 transient_cache: ProviderCache,
25 inquirer: Option<ProviderCacheKey>,
26 resolution_stack: Option<ProviderResolutionStack>,
27}
28
29#[derive(Default)]
30struct AsyncProviderSeedState {
31 complete: BTreeSet<ProviderCacheKey>,
32 visiting: Vec<(ProviderCacheKey, ProviderToken)>,
33}
34
35impl AsyncProviderSeedState {
36 fn enter(&mut self, entry: &ProviderEntry) -> Result<bool> {
37 let cache_key = entry.cache_key();
38 if self.complete.contains(&cache_key) {
39 return Ok(false);
40 }
41 if let Some(index) = self
42 .visiting
43 .iter()
44 .position(|(active, _)| *active == cache_key)
45 {
46 let mut chain = self.visiting[index..]
47 .iter()
48 .map(|(_, token)| token.to_string())
49 .collect::<Vec<_>>();
50 chain.push(entry.token().to_string());
51 return Err(BootError::Internal(format!(
52 "cyclic async provider dependency detected: {}",
53 chain.join(" -> ")
54 )));
55 }
56
57 self.visiting.push((cache_key, entry.token().clone()));
58 Ok(true)
59 }
60
61 fn exit(&mut self, cache_key: ProviderCacheKey, complete: bool) -> Result<()> {
62 let Some((active, _)) = self.visiting.pop() else {
63 return Err(BootError::Internal(
64 "async provider dependency stack underflow".to_string(),
65 ));
66 };
67 if active != cache_key {
68 return Err(BootError::Internal(
69 "async provider dependency stack is inconsistent".to_string(),
70 ));
71 }
72 if complete {
73 self.complete.insert(cache_key);
74 }
75 Ok(())
76 }
77}
78
79impl fmt::Debug for ModuleRef {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 let len = self
82 .providers
83 .read()
84 .map(|providers| providers.len())
85 .unwrap_or(0);
86 let visible = self
87 .visible_scopes
88 .read()
89 .map(|scopes| scopes.len())
90 .unwrap_or(0);
91 f.debug_struct("ModuleRef")
92 .field("providers", &len)
93 .field("visible_scopes", &visible)
94 .finish()
95 }
96}
97
98impl ModuleRef {
99 pub fn new() -> Self {
100 Self::default()
101 }
102
103 pub fn request_scope(&self) -> Self {
104 self.context_scope(&ContextIdFactory::create())
105 }
106
107 pub fn context_scope(&self, context_id: &ContextId) -> Self {
109 Self {
110 providers: Arc::clone(&self.providers),
111 provider_order: Arc::clone(&self.provider_order),
112 visible_scopes: Arc::clone(&self.visible_scopes),
113 context_id: Some(context_id.clone()),
114 transient_cache: self.transient_cache.clone(),
115 inquirer: self.inquirer,
116 resolution_stack: self.resolution_stack.clone(),
117 }
118 }
119
120 pub(crate) fn weak_context_scope(&self, context_id: &ContextId) -> Self {
121 Self {
122 providers: Arc::clone(&self.providers),
123 provider_order: Arc::clone(&self.provider_order),
124 visible_scopes: Arc::clone(&self.visible_scopes),
125 context_id: Some(context_id.downgrade()),
126 transient_cache: self.transient_cache.clone(),
127 inquirer: self.inquirer,
128 resolution_stack: self.resolution_stack.clone(),
129 }
130 }
131
132 pub fn context_id(&self) -> Option<&ContextId> {
134 self.context_id.as_ref()
135 }
136
137 pub(crate) fn with_resolution_stack(&self, resolution_stack: ProviderResolutionStack) -> Self {
138 Self {
139 providers: Arc::clone(&self.providers),
140 provider_order: Arc::clone(&self.provider_order),
141 visible_scopes: Arc::clone(&self.visible_scopes),
142 context_id: self.context_id.clone(),
143 transient_cache: self.transient_cache.clone(),
144 inquirer: self.inquirer,
145 resolution_stack: Some(resolution_stack),
146 }
147 }
148
149 pub(crate) fn without_resolution_stack(&self) -> Self {
150 Self {
151 providers: Arc::clone(&self.providers),
152 provider_order: Arc::clone(&self.provider_order),
153 visible_scopes: Arc::clone(&self.visible_scopes),
154 context_id: self.context_id.clone(),
155 transient_cache: self.transient_cache.clone(),
156 inquirer: self.inquirer,
157 resolution_stack: None,
158 }
159 }
160
161 pub(crate) fn with_inquirer(&self, inquirer: ProviderCacheKey) -> Self {
162 Self {
163 providers: Arc::clone(&self.providers),
164 provider_order: Arc::clone(&self.provider_order),
165 visible_scopes: Arc::clone(&self.visible_scopes),
166 context_id: self.context_id.clone(),
167 transient_cache: self.transient_cache.clone(),
168 inquirer: Some(inquirer),
169 resolution_stack: self.resolution_stack.clone(),
170 }
171 }
172
173 pub(crate) fn without_context(&self) -> Self {
174 Self {
175 providers: Arc::clone(&self.providers),
176 provider_order: Arc::clone(&self.provider_order),
177 visible_scopes: Arc::clone(&self.visible_scopes),
178 context_id: None,
179 transient_cache: self.transient_cache.clone(),
180 inquirer: self.inquirer,
181 resolution_stack: self.resolution_stack.clone(),
182 }
183 }
184
185 pub(crate) fn with_transient_cache(&self, transient_cache: ProviderCache) -> Self {
186 Self {
187 providers: Arc::clone(&self.providers),
188 provider_order: Arc::clone(&self.provider_order),
189 visible_scopes: Arc::clone(&self.visible_scopes),
190 context_id: self.context_id.clone(),
191 transient_cache,
192 inquirer: self.inquirer,
193 resolution_stack: self.resolution_stack.clone(),
194 }
195 }
196
197 pub(crate) fn transient_cache(&self) -> ProviderCache {
198 self.transient_cache.clone()
199 }
200
201 pub fn register(&self, definition: ProviderDefinition) -> Result<()> {
202 let token = definition.token().clone();
203 self.validate_registration(&token, &definition)?;
204 if definition.is_async_factory() {
205 return Err(BootError::Internal(format!(
206 "async provider factory requires async registration: {token}"
207 )));
208 }
209
210 let entry = ProviderEntry::new(definition);
211 self.insert_entry(token, entry)
212 }
213
214 pub async fn register_async(&self, definition: ProviderDefinition) -> Result<()> {
215 let token = definition.token().clone();
216 self.validate_registration(&token, &definition)?;
217
218 let entry = ProviderEntry::new(definition);
219 self.insert_entry(token, entry)
220 }
221
222 pub fn insert<T>(&self, value: T) -> Result<()>
223 where
224 T: Send + Sync + 'static,
225 {
226 self.insert_arc(Arc::new(value))
227 }
228
229 pub fn insert_arc<T>(&self, value: Arc<T>) -> Result<()>
230 where
231 T: Send + Sync + 'static,
232 {
233 let token = ProviderToken::of::<T>();
234 let entry = ProviderEntry::new(ProviderDefinition::from_arc(value));
235 self.insert_entry(token, entry)
236 }
237
238 pub fn get<T>(&self) -> Result<Arc<T>>
239 where
240 T: Send + Sync + 'static,
241 {
242 self.get_token::<T>(&ProviderToken::of::<T>())
243 }
244
245 pub fn get_named<T>(&self, token: &str) -> Result<Arc<T>>
246 where
247 T: Send + Sync + 'static,
248 {
249 self.get_token::<T>(&ProviderToken::named(token))
250 }
251
252 pub fn get_optional<T>(&self) -> Result<Option<Arc<T>>>
253 where
254 T: Send + Sync + 'static,
255 {
256 self.get_optional_token::<T>(&ProviderToken::of::<T>())
257 }
258
259 pub fn get_optional_named<T>(&self, token: &str) -> Result<Option<Arc<T>>>
260 where
261 T: Send + Sync + 'static,
262 {
263 self.get_optional_token::<T>(&ProviderToken::named(token))
264 }
265
266 pub fn provider_ref<T>(&self) -> ProviderRef<T>
268 where
269 T: Send + Sync + 'static,
270 {
271 ProviderRef::new(self.clone(), ProviderToken::of::<T>())
272 }
273
274 pub fn named_provider_ref<T>(&self, token: &str) -> ProviderRef<T>
276 where
277 T: Send + Sync + 'static,
278 {
279 ProviderRef::new(self.clone(), ProviderToken::named(token))
280 }
281
282 pub fn optional_provider_ref<T>(&self) -> Result<Option<ProviderRef<T>>>
284 where
285 T: Send + Sync + 'static,
286 {
287 if self.contains_provider::<T>()? {
288 Ok(Some(self.provider_ref::<T>()))
289 } else {
290 Ok(None)
291 }
292 }
293
294 pub fn optional_named_provider_ref<T>(&self, token: &str) -> Result<Option<ProviderRef<T>>>
296 where
297 T: Send + Sync + 'static,
298 {
299 if self.contains_named(token)? {
300 Ok(Some(self.named_provider_ref::<T>(token)))
301 } else {
302 Ok(None)
303 }
304 }
305
306 pub fn resolve<T>(&self) -> Result<Arc<T>>
312 where
313 T: Send + Sync + 'static,
314 {
315 self.resolve_token::<T>(&ProviderToken::of::<T>())
316 }
317
318 pub fn resolve_with_context<T>(&self, context_id: &ContextId) -> Result<Arc<T>>
320 where
321 T: Send + Sync + 'static,
322 {
323 self.resolve_token_with_context::<T>(&ProviderToken::of::<T>(), context_id)
324 }
325
326 pub fn resolve_named<T>(&self, token: &str) -> Result<Arc<T>>
328 where
329 T: Send + Sync + 'static,
330 {
331 self.resolve_token::<T>(&ProviderToken::named(token))
332 }
333
334 pub fn resolve_named_with_context<T>(
336 &self,
337 token: &str,
338 context_id: &ContextId,
339 ) -> Result<Arc<T>>
340 where
341 T: Send + Sync + 'static,
342 {
343 self.resolve_token_with_context::<T>(&ProviderToken::named(token), context_id)
344 }
345
346 pub fn resolve_optional<T>(&self) -> Result<Option<Arc<T>>>
348 where
349 T: Send + Sync + 'static,
350 {
351 self.resolve_optional_token::<T>(&ProviderToken::of::<T>())
352 }
353
354 pub fn resolve_optional_with_context<T>(&self, context_id: &ContextId) -> Result<Option<Arc<T>>>
356 where
357 T: Send + Sync + 'static,
358 {
359 self.resolve_optional_token_with_context::<T>(&ProviderToken::of::<T>(), context_id)
360 }
361
362 pub fn resolve_optional_named<T>(&self, token: &str) -> Result<Option<Arc<T>>>
364 where
365 T: Send + Sync + 'static,
366 {
367 self.resolve_optional_token::<T>(&ProviderToken::named(token))
368 }
369
370 pub fn resolve_optional_named_with_context<T>(
372 &self,
373 token: &str,
374 context_id: &ContextId,
375 ) -> Result<Option<Arc<T>>>
376 where
377 T: Send + Sync + 'static,
378 {
379 self.resolve_optional_token_with_context::<T>(&ProviderToken::named(token), context_id)
380 }
381
382 pub fn create<T>(&self) -> Result<T>
384 where
385 T: FromModuleRef,
386 {
387 let inquirer = ProviderCacheKey::next();
388 let token = ProviderToken::of::<T>();
389 let (resolution_stack, _guard) =
390 enter_resolution_stack(&new_resolution_stack(), inquirer, &token)?;
391 let factory_ref = self
392 .with_transient_cache(new_provider_cache())
393 .with_inquirer(inquirer)
394 .with_resolution_stack(resolution_stack);
395 T::from_module_ref(&factory_ref)
396 }
397
398 pub fn create_arc<T>(&self) -> Result<Arc<T>>
400 where
401 T: FromModuleRef,
402 {
403 Ok(Arc::new(self.create::<T>()?))
404 }
405
406 pub fn contains(&self, token: &ProviderToken) -> Result<bool> {
407 Ok(self.get_entry(token)?.is_some())
408 }
409
410 pub fn contains_provider<T>(&self) -> Result<bool>
411 where
412 T: Send + Sync + 'static,
413 {
414 self.contains(&ProviderToken::of::<T>())
415 }
416
417 pub fn contains_named(&self, token: &str) -> Result<bool> {
418 self.contains(&ProviderToken::named(token))
419 }
420
421 pub fn provider_is_contextual<T>(&self) -> Result<bool>
426 where
427 T: Send + Sync + 'static,
428 {
429 self.token_is_contextual(&ProviderToken::of::<T>())
430 }
431
432 pub fn provider_scope<T>(&self) -> Result<ProviderScope>
434 where
435 T: Send + Sync + 'static,
436 {
437 self.token_scope(&ProviderToken::of::<T>())
438 }
439
440 pub fn named_provider_is_contextual(&self, token: &str) -> Result<bool> {
442 self.token_is_contextual(&ProviderToken::named(token))
443 }
444
445 pub fn named_provider_scope(&self, token: &str) -> Result<ProviderScope> {
447 self.token_scope(&ProviderToken::named(token))
448 }
449
450 pub(crate) fn token_is_contextual(&self, token: &ProviderToken) -> Result<bool> {
451 let entry = self
452 .get_entry(token)?
453 .ok_or_else(|| BootError::MissingProvider(token.to_string()))?;
454 Ok(entry.resolution_plan(self)?.is_contextual())
455 }
456
457 pub(crate) fn token_scope(&self, token: &ProviderToken) -> Result<ProviderScope> {
458 let entry = self
459 .get_entry(token)?
460 .ok_or_else(|| BootError::MissingProvider(token.to_string()))?;
461 Ok(entry.resolution_plan(self)?.scope())
462 }
463
464 pub fn tokens(&self) -> Result<Vec<ProviderToken>> {
465 let mut tokens = BTreeMap::new();
466 self.collect_tokens(&mut tokens)?;
467 Ok(tokens.into_keys().collect())
468 }
469
470 fn insert_entry(&self, token: ProviderToken, entry: ProviderEntry) -> Result<()> {
471 let mut provider_order = self.write_provider_order()?;
472 let mut providers = self.write_providers()?;
473 if providers.contains_key(&token) {
474 return Err(BootError::DuplicateProvider(token.to_string()));
475 }
476 providers.insert(token.clone(), entry);
477 provider_order.push(token);
478 Ok(())
479 }
480
481 fn validate_registration(
482 &self,
483 token: &ProviderToken,
484 definition: &ProviderDefinition,
485 ) -> Result<()> {
486 if self.contains_local(token)? {
487 return Err(BootError::DuplicateProvider(token.to_string()));
488 }
489 if definition.is_async_factory() && definition.scope() != ProviderScope::Singleton {
490 return Err(BootError::Internal(format!(
491 "async provider factories require singleton scope: {token}"
492 )));
493 }
494 if definition.lifecycle().has_hooks() && definition.scope() != ProviderScope::Singleton {
495 return Err(BootError::Internal(format!(
496 "provider lifecycle hooks require singleton scope: {token}"
497 )));
498 }
499 if definition.lifecycle().has_hooks() && definition.is_alias() {
500 return Err(BootError::Internal(format!(
501 "provider aliases cannot define lifecycle hooks: {token}"
502 )));
503 }
504 Ok(())
505 }
506
507 pub(crate) fn add_visible_scope(&self, module_ref: ModuleRef) -> Result<()> {
508 self.write_visible_scopes()?.push(module_ref);
509 Ok(())
510 }
511
512 pub(crate) fn export_from(&self, module_ref: &ModuleRef, token: &ProviderToken) -> Result<()> {
513 let entry = module_ref
514 .get_entry(token)?
515 .ok_or_else(|| BootError::MissingProvider(token.to_string()))?;
516 self.insert_entry(token.clone(), entry.with_owner(module_ref.clone()))
517 }
518
519 pub(crate) fn local_tokens(&self) -> Result<Vec<ProviderToken>> {
520 Ok(self.read_provider_order()?.clone())
521 }
522
523 pub(crate) fn initialize_local_singletons(&self) -> Result<()> {
524 for entry in self.local_entries()? {
525 let plan = entry.resolution_plan(self)?;
526 self.validate_resolution_plan(&entry, plan)?;
527 if plan.scope() == ProviderScope::Singleton
528 && !plan.is_contextual()
529 && !entry.is_alias()
530 {
531 let resolution_stack = new_resolution_stack();
532 entry.resolve_singleton(self, self.transient_cache(), &resolution_stack)?;
533 }
534 }
535 Ok(())
536 }
537
538 pub(crate) fn validate_local_resolution_plans(&self) -> Result<()> {
539 for entry in self.local_entries()? {
540 let plan = entry.resolution_plan(self)?;
541 self.validate_resolution_plan(&entry, plan)?;
542 }
543 Ok(())
544 }
545
546 pub(crate) async fn seed_local_async_singletons(&self) -> Result<()> {
547 let entries = self.local_entries()?;
548 for entry in &entries {
549 let plan = entry.resolution_plan(self)?;
550 self.validate_resolution_plan(entry, plan)?;
551 }
552
553 let mut state = AsyncProviderSeedState::default();
554 for entry in entries {
555 let plan = entry.resolution_plan(self)?;
556 if plan.scope() == ProviderScope::Singleton
557 && !plan.is_contextual()
558 && !entry.is_alias()
559 && entry.is_async_factory()
560 {
561 self.seed_async_dependency_tree(entry, &mut state).await?;
562 }
563 }
564 Ok(())
565 }
566
567 fn seed_async_dependency_tree<'a>(
568 &'a self,
569 entry: ProviderEntry,
570 state: &'a mut AsyncProviderSeedState,
571 ) -> BoxFuture<'a, Result<()>> {
572 Box::pin(async move {
573 let cache_key = entry.cache_key();
574 if !state.enter(&entry)? {
575 return Ok(());
576 }
577
578 let owner = entry.owner_module_ref(self);
579 let result = async {
580 let plan = entry.resolution_plan(&owner)?;
581 owner.validate_resolution_plan(&entry, plan)?;
582 for dependency in entry.eager_dependency_entries(&owner)? {
583 owner.seed_async_dependency_tree(dependency, state).await?;
584 }
585 if entry.is_async_factory() {
586 entry.seed_singleton_async(owner).await?;
587 }
588 Ok(())
589 }
590 .await;
591 let exit_result = state.exit(cache_key, result.is_ok());
592 match (result, exit_result) {
593 (Ok(()), Ok(())) => Ok(()),
594 (Err(error), _) => Err(error),
595 (Ok(()), Err(error)) => Err(error),
596 }
597 })
598 }
599
600 fn validate_resolution_plan(
601 &self,
602 entry: &ProviderEntry,
603 plan: super::entry::ProviderResolutionPlan,
604 ) -> Result<()> {
605 if plan.is_contextual() && entry.is_async_factory() {
606 return Err(BootError::Internal(format!(
607 "async provider `{}` cannot depend on a request-context provider",
608 entry.token()
609 )));
610 }
611 if plan.is_contextual() && entry.has_lifecycle_hooks() {
612 return Err(BootError::Internal(format!(
613 "provider `{}` cannot use singleton lifecycle hooks because request scope propagated through its dependencies",
614 entry.token()
615 )));
616 }
617 Ok(())
618 }
619
620 pub(crate) fn initialize_local_providers(&self) -> Result<()> {
621 for entry in self.local_entries()? {
622 entry.on_module_init(self)?;
623 }
624 Ok(())
625 }
626
627 pub(crate) async fn bootstrap_local_providers(&self) -> Result<()> {
628 for entry in self.local_entries()? {
629 entry.on_application_bootstrap(self.clone()).await?;
630 }
631 Ok(())
632 }
633
634 pub(crate) async fn destroy_local_providers(&self, signal: Option<String>) -> Result<()> {
635 let mut entries = self.local_entries()?;
636 entries.reverse();
637 for entry in entries {
638 entry
639 .on_module_destroy(self.clone(), signal.clone())
640 .await?;
641 }
642 Ok(())
643 }
644
645 pub(crate) async fn before_application_shutdown_local_providers(
646 &self,
647 signal: Option<String>,
648 ) -> Result<()> {
649 let mut entries = self.local_entries()?;
650 entries.reverse();
651 for entry in entries {
652 entry
653 .before_application_shutdown(self.clone(), signal.clone())
654 .await?;
655 }
656 Ok(())
657 }
658
659 pub(crate) async fn shutdown_local_providers(&self, signal: Option<String>) -> Result<()> {
660 let mut entries = self.local_entries()?;
661 entries.reverse();
662 for entry in entries {
663 entry
664 .on_application_shutdown(self.clone(), signal.clone())
665 .await?;
666 }
667 Ok(())
668 }
669
670 pub(crate) fn get_token<T>(&self, token: &ProviderToken) -> Result<Arc<T>>
671 where
672 T: Send + Sync + 'static,
673 {
674 let value = self
675 .get_any(token)?
676 .ok_or_else(|| BootError::MissingProvider(token.to_string()))?;
677
678 Arc::downcast::<T>(value).map_err(|_| BootError::ProviderTypeMismatch(token.to_string()))
679 }
680
681 pub(crate) fn get_optional_token<T>(&self, token: &ProviderToken) -> Result<Option<Arc<T>>>
682 where
683 T: Send + Sync + 'static,
684 {
685 let value = self.get_any(token)?;
686 match value {
687 Some(value) => Arc::downcast::<T>(value)
688 .map(Some)
689 .map_err(|_| BootError::ProviderTypeMismatch(token.to_string())),
690 None => Ok(None),
691 }
692 }
693
694 pub(crate) fn resolve_token<T>(&self, token: &ProviderToken) -> Result<Arc<T>>
695 where
696 T: Send + Sync + 'static,
697 {
698 self.resolve_token_with_context(token, &ContextIdFactory::create())
699 }
700
701 pub(crate) fn resolve_token_with_context<T>(
702 &self,
703 token: &ProviderToken,
704 context_id: &ContextId,
705 ) -> Result<Arc<T>>
706 where
707 T: Send + Sync + 'static,
708 {
709 self.context_scope(context_id).get_token(token)
710 }
711
712 pub(crate) fn resolve_optional_token<T>(&self, token: &ProviderToken) -> Result<Option<Arc<T>>>
713 where
714 T: Send + Sync + 'static,
715 {
716 self.resolve_optional_token_with_context(token, &ContextIdFactory::create())
717 }
718
719 pub(crate) fn resolve_optional_token_with_context<T>(
720 &self,
721 token: &ProviderToken,
722 context_id: &ContextId,
723 ) -> Result<Option<Arc<T>>>
724 where
725 T: Send + Sync + 'static,
726 {
727 self.context_scope(context_id).get_optional_token(token)
728 }
729
730 fn get_any(&self, token: &ProviderToken) -> Result<Option<Arc<AnyProvider>>> {
731 let mut alias_path = Vec::new();
732 let resolution_stack = match &self.resolution_stack {
733 Some(resolution_stack) if !resolution_stack_is_empty(resolution_stack) => {
734 Arc::clone(resolution_stack)
735 }
736 Some(_) | None => new_resolution_stack(),
737 };
738 self.get_any_with_context_inner(
739 token,
740 self.context_id.clone(),
741 self.transient_cache.clone(),
742 self.inquirer,
743 &resolution_stack,
744 &mut alias_path,
745 )
746 }
747
748 pub(crate) fn get_any_with_context_inner(
749 &self,
750 token: &ProviderToken,
751 context_id: Option<ContextId>,
752 transient_cache: ProviderCache,
753 inquirer: Option<ProviderCacheKey>,
754 resolution_stack: &ProviderResolutionStack,
755 alias_path: &mut Vec<ProviderToken>,
756 ) -> Result<Option<Arc<AnyProvider>>> {
757 if let Some(entry) = self.read_providers()?.get(token).cloned() {
758 return entry
759 .resolve(
760 self,
761 context_id,
762 transient_cache,
763 inquirer,
764 resolution_stack,
765 alias_path,
766 )
767 .map(Some);
768 }
769
770 for scope in self.visible_scopes()? {
771 if let Some(value) = scope.get_any_with_context_inner(
772 token,
773 context_id.clone(),
774 transient_cache.clone(),
775 inquirer,
776 resolution_stack,
777 alias_path,
778 )? {
779 return Ok(Some(value));
780 }
781 }
782
783 Ok(None)
784 }
785
786 pub(crate) fn get_entry(&self, token: &ProviderToken) -> Result<Option<ProviderEntry>> {
787 if let Some(entry) = self.read_providers()?.get(token).cloned() {
788 return Ok(Some(entry.with_owner(self.clone())));
789 }
790
791 for scope in self.visible_scopes()? {
792 if let Some(entry) = scope.get_entry(token)? {
793 return Ok(Some(entry));
794 }
795 }
796
797 Ok(None)
798 }
799
800 fn contains_local(&self, token: &ProviderToken) -> Result<bool> {
801 Ok(self.read_providers()?.contains_key(token))
802 }
803
804 fn collect_tokens(&self, tokens: &mut BTreeMap<ProviderToken, ()>) -> Result<()> {
805 for token in self.read_providers()?.keys() {
806 tokens.insert(token.clone(), ());
807 }
808 for scope in self.visible_scopes()? {
809 scope.collect_tokens(tokens)?;
810 }
811 Ok(())
812 }
813
814 fn local_entries(&self) -> Result<Vec<ProviderEntry>> {
815 let provider_order = self.read_provider_order()?.clone();
816 let providers = self.read_providers()?;
817 let mut entries = Vec::with_capacity(provider_order.len());
818 for token in provider_order {
819 if let Some(entry) = providers.get(&token) {
820 entries.push(entry.clone());
821 }
822 }
823 Ok(entries)
824 }
825
826 fn visible_scopes(&self) -> Result<Vec<ModuleRef>> {
827 Ok(self.read_visible_scopes()?.clone())
828 }
829
830 fn read_providers(
831 &self,
832 ) -> Result<std::sync::RwLockReadGuard<'_, BTreeMap<ProviderToken, ProviderEntry>>> {
833 self.providers
834 .read()
835 .map_err(|_| BootError::Internal("provider registry lock is poisoned".to_string()))
836 }
837
838 fn write_providers(
839 &self,
840 ) -> Result<std::sync::RwLockWriteGuard<'_, BTreeMap<ProviderToken, ProviderEntry>>> {
841 self.providers
842 .write()
843 .map_err(|_| BootError::Internal("provider registry lock is poisoned".to_string()))
844 }
845
846 fn read_provider_order(&self) -> Result<std::sync::RwLockReadGuard<'_, Vec<ProviderToken>>> {
847 self.provider_order
848 .read()
849 .map_err(|_| BootError::Internal("provider order lock is poisoned".to_string()))
850 }
851
852 fn write_provider_order(&self) -> Result<std::sync::RwLockWriteGuard<'_, Vec<ProviderToken>>> {
853 self.provider_order
854 .write()
855 .map_err(|_| BootError::Internal("provider order lock is poisoned".to_string()))
856 }
857
858 fn read_visible_scopes(&self) -> Result<std::sync::RwLockReadGuard<'_, Vec<ModuleRef>>> {
859 self.visible_scopes
860 .read()
861 .map_err(|_| BootError::Internal("provider registry lock is poisoned".to_string()))
862 }
863
864 fn write_visible_scopes(&self) -> Result<std::sync::RwLockWriteGuard<'_, Vec<ModuleRef>>> {
865 self.visible_scopes
866 .write()
867 .map_err(|_| BootError::Internal("provider registry lock is poisoned".to_string()))
868 }
869}