qubit_spi/provider_registry.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! Typed registry for pluggable service providers.
11
12use std::collections::{
13 HashMap,
14 HashSet,
15};
16use std::marker::PhantomData;
17use std::rc::Rc;
18use std::sync::Arc;
19
20use log::{
21 debug,
22 trace,
23};
24
25use crate::{
26 ProviderAvailability,
27 ProviderCreateError,
28 ProviderDescriptor,
29 ProviderFailure,
30 ProviderName,
31 ProviderRegistryError,
32 ProviderSelection,
33 ServiceProvider,
34 ServiceSpec,
35};
36
37/// Registry of providers for one service specification.
38///
39/// Provider descriptors are captured during registration. Provider ids and
40/// aliases are normalized into [`ProviderName`] values and indexed
41/// case-insensitively, so lookup does not depend on provider metadata changing
42/// after registration. Automatic selection order is cached during registration
43/// updates. Registries store providers behind shared trait objects, so
44/// registered providers and service specifications must be `'static`.
45#[derive(Debug)]
46pub struct ProviderRegistry<Spec>
47where
48 Spec: ServiceSpec + 'static,
49{
50 /// Registered providers in insertion order.
51 providers: Vec<ProviderEntry<Spec>>,
52 /// Normalized provider id and alias lookup table.
53 index: HashMap<ProviderName, usize>,
54 /// Cached automatic-selection candidates ordered by priority and id.
55 auto_candidates: Vec<ProviderName>,
56 /// Keeps the service specification attached to this registry type.
57 marker: PhantomData<fn() -> Spec>,
58}
59
60/// Registered provider and its captured descriptor.
61#[derive(Debug)]
62struct ProviderEntry<Spec>
63where
64 Spec: ServiceSpec + 'static,
65{
66 /// Captured provider descriptor.
67 descriptor: ProviderDescriptor,
68 /// Provider factory.
69 provider: Arc<dyn ServiceProvider<Spec>>,
70}
71
72impl<Spec> ProviderRegistry<Spec>
73where
74 Spec: ServiceSpec + 'static,
75{
76 /// Creates an empty provider registry.
77 ///
78 /// # Returns
79 /// Empty provider registry.
80 #[inline]
81 pub fn new() -> Self {
82 Self::default()
83 }
84
85 /// Gets the number of registered providers.
86 ///
87 /// # Returns
88 /// Provider count.
89 #[inline]
90 pub fn len(&self) -> usize {
91 self.providers.len()
92 }
93
94 /// Tells whether this registry contains no providers.
95 ///
96 /// # Returns
97 /// `true` when no providers are registered.
98 #[inline]
99 pub fn is_empty(&self) -> bool {
100 self.providers.is_empty()
101 }
102
103 /// Registers a provider owned by the registry.
104 ///
105 /// # Parameters
106 /// - `provider`: Provider to register.
107 ///
108 /// # Errors
109 /// Returns [`ProviderRegistryError`] when the provider descriptor is invalid
110 /// or when its id or aliases conflict with an existing provider.
111 #[inline]
112 pub fn register<P>(&mut self, provider: P) -> Result<(), ProviderRegistryError>
113 where
114 P: ServiceProvider<Spec> + 'static,
115 {
116 self.register_provider(Arc::new(provider))
117 }
118
119 /// Registers a shared provider.
120 ///
121 /// # Parameters
122 /// - `provider`: Shared provider to register.
123 ///
124 /// # Errors
125 /// Returns [`ProviderRegistryError`] when the provider descriptor is invalid
126 /// or when its id or aliases conflict with an existing provider.
127 #[inline]
128 pub fn register_shared(
129 &mut self,
130 provider: Arc<dyn ServiceProvider<Spec>>,
131 ) -> Result<(), ProviderRegistryError> {
132 self.register_provider(provider)
133 }
134
135 /// Registers a provider stored behind a trait object.
136 ///
137 /// # Parameters
138 /// - `provider`: Shared provider trait object to register.
139 ///
140 /// # Errors
141 /// Returns [`ProviderRegistryError`] when the provider descriptor is invalid
142 /// or when its id or aliases conflict with an existing provider.
143 fn register_provider(
144 &mut self,
145 provider: Arc<dyn ServiceProvider<Spec>>,
146 ) -> Result<(), ProviderRegistryError> {
147 let descriptor = provider.descriptor()?;
148 self.validate_descriptor(&descriptor)?;
149 let provider_index = self.providers.len();
150 for name in descriptor.names() {
151 self.index.insert(name.clone(), provider_index);
152 }
153 self.providers.push(ProviderEntry {
154 descriptor,
155 provider,
156 });
157 self.rebuild_auto_candidates();
158 debug!(
159 "registered provider '{}' with {} aliases and priority {}",
160 self.providers[provider_index].descriptor.id(),
161 self.providers[provider_index].descriptor.aliases().len(),
162 self.providers[provider_index].descriptor.priority(),
163 );
164 Ok(())
165 }
166
167 /// Gets canonical provider ids in registration order.
168 ///
169 /// # Returns
170 /// Registered provider ids.
171 #[inline]
172 pub fn provider_names(&self) -> Vec<&str> {
173 self.iter_provider_names().collect()
174 }
175
176 /// Iterates over canonical provider ids in registration order.
177 ///
178 /// # Returns
179 /// Iterator over registered provider ids.
180 #[inline]
181 pub fn iter_provider_names(&self) -> impl Iterator<Item = &str> + '_ {
182 self.providers
183 .iter()
184 .map(|entry| entry.descriptor.id().as_str())
185 }
186
187 /// Gets captured provider descriptors in registration order.
188 ///
189 /// # Returns
190 /// Provider descriptors captured during registration.
191 #[inline]
192 pub fn provider_descriptors(&self) -> Vec<&ProviderDescriptor> {
193 self.iter_provider_descriptors().collect()
194 }
195
196 /// Iterates over captured provider descriptors in registration order.
197 ///
198 /// # Returns
199 /// Iterator over provider descriptors captured during registration.
200 #[inline]
201 pub fn iter_provider_descriptors(&self) -> impl Iterator<Item = &ProviderDescriptor> + '_ {
202 self.providers.iter().map(|entry| &entry.descriptor)
203 }
204
205 /// Finds a provider by id or alias.
206 ///
207 /// # Parameters
208 /// - `name`: Provider id or alias. Names are normalized before lookup.
209 ///
210 /// # Returns
211 /// Matching provider, or `None` when no provider matches or `name` is
212 /// invalid.
213 #[inline]
214 pub fn find_provider(&self, name: &str) -> Option<&dyn ServiceProvider<Spec>> {
215 self.resolve_provider(name).ok()
216 }
217
218 /// Resolves a provider by id or alias.
219 ///
220 /// # Parameters
221 /// - `name`: Provider id or alias. Names are normalized before lookup.
222 ///
223 /// # Returns
224 /// Matching provider.
225 ///
226 /// # Errors
227 /// Returns [`ProviderRegistryError::EmptyProviderName`] or
228 /// [`ProviderRegistryError::InvalidProviderName`] when `name` is invalid,
229 /// or [`ProviderRegistryError::UnknownProvider`] when no provider matches.
230 pub fn resolve_provider(
231 &self,
232 name: &str,
233 ) -> Result<&dyn ServiceProvider<Spec>, ProviderRegistryError> {
234 let name = match ProviderName::new(name) {
235 Ok(name) => name,
236 Err(error) => {
237 trace!("provider resolution rejected invalid name: {error}");
238 return Err(error);
239 }
240 };
241 let Some(entry) = self.find_entry_by_name(&name) else {
242 trace!("provider resolution missed provider '{name}'");
243 return Err(ProviderRegistryError::UnknownProvider { name });
244 };
245 trace!(
246 "provider resolution matched '{}' to registered provider '{}'",
247 name,
248 entry.descriptor.id(),
249 );
250 Ok(entry.provider.as_ref())
251 }
252
253 /// Creates a boxed service from one provider name.
254 ///
255 /// # Parameters
256 /// - `name`: Provider id or alias.
257 /// - `config`: Configuration passed to the provider.
258 ///
259 /// # Returns
260 /// Boxed service value created by the selected provider.
261 ///
262 /// # Errors
263 /// Returns [`ProviderRegistryError::EmptyProviderName`] or
264 /// [`ProviderRegistryError::InvalidProviderName`] when `name` is invalid,
265 /// [`ProviderRegistryError::UnknownProvider`] when no provider matches,
266 /// [`ProviderRegistryError::ProviderUnavailable`] when the provider is not
267 /// available, or [`ProviderRegistryError::ProviderCreate`] when the provider
268 /// factory fails.
269 #[inline]
270 pub fn create_box(
271 &self,
272 name: &str,
273 config: &Spec::Config,
274 ) -> Result<Box<Spec::Service>, ProviderRegistryError> {
275 self.create_with(name, config, |provider, config| provider.create_box(config))
276 }
277
278 /// Creates an atomically shared service from one provider name.
279 ///
280 /// # Parameters
281 /// - `name`: Provider id or alias.
282 /// - `config`: Configuration passed to the provider.
283 ///
284 /// # Returns
285 /// Atomically shared service value created by the selected provider.
286 ///
287 /// # Errors
288 /// Returns [`ProviderRegistryError::EmptyProviderName`] or
289 /// [`ProviderRegistryError::InvalidProviderName`] when `name` is invalid,
290 /// [`ProviderRegistryError::UnknownProvider`] when no provider matches,
291 /// [`ProviderRegistryError::ProviderUnavailable`] when the provider is not
292 /// available, or [`ProviderRegistryError::ProviderCreate`] when the provider
293 /// factory fails.
294 #[inline]
295 pub fn create_arc(
296 &self,
297 name: &str,
298 config: &Spec::Config,
299 ) -> Result<Arc<Spec::Service>, ProviderRegistryError> {
300 self.create_with(name, config, |provider, config| provider.create_arc(config))
301 }
302
303 /// Creates a locally shared service from one provider name.
304 ///
305 /// # Parameters
306 /// - `name`: Provider id or alias.
307 /// - `config`: Configuration passed to the provider.
308 ///
309 /// # Returns
310 /// Locally shared service value created by the selected provider.
311 ///
312 /// # Errors
313 /// Returns [`ProviderRegistryError::EmptyProviderName`] or
314 /// [`ProviderRegistryError::InvalidProviderName`] when `name` is invalid,
315 /// [`ProviderRegistryError::UnknownProvider`] when no provider matches,
316 /// [`ProviderRegistryError::ProviderUnavailable`] when the provider is not
317 /// available, or [`ProviderRegistryError::ProviderCreate`] when the provider
318 /// factory fails.
319 #[inline]
320 pub fn create_rc(
321 &self,
322 name: &str,
323 config: &Spec::Config,
324 ) -> Result<Rc<Spec::Service>, ProviderRegistryError> {
325 self.create_with(name, config, |provider, config| provider.create_rc(config))
326 }
327
328 /// Creates a service handle from one provider name.
329 ///
330 /// # Parameters
331 /// - `name`: Provider id or alias.
332 /// - `config`: Configuration passed to the provider.
333 /// - `create`: Provider factory method used to create the handle.
334 ///
335 /// # Returns
336 /// Service handle created by the selected provider.
337 ///
338 /// # Errors
339 /// Returns [`ProviderRegistryError`] when the provider name is invalid,
340 /// unknown, unavailable, or when the provider factory fails.
341 fn create_with<Handle, Create>(
342 &self,
343 name: &str,
344 config: &Spec::Config,
345 create: Create,
346 ) -> Result<Handle, ProviderRegistryError>
347 where
348 Create:
349 Fn(&dyn ServiceProvider<Spec>, &Spec::Config) -> Result<Handle, ProviderCreateError>,
350 {
351 let name = ProviderName::new(name)?;
352 let entry = self
353 .find_entry_by_name(&name)
354 .ok_or_else(|| ProviderRegistryError::UnknownProvider { name: name.clone() })?;
355 trace!("creating service from provider '{name}'");
356 match entry.provider.availability(config) {
357 ProviderAvailability::Available => match create(entry.provider.as_ref(), config) {
358 Ok(service) => {
359 debug!("provider '{name}' created service");
360 Ok(service)
361 }
362 Err(error) => {
363 trace!(
364 "provider '{name}' failed to create service: {}",
365 error.reason(),
366 );
367 Err(registry_error_from_create_error(name, error))
368 }
369 },
370 ProviderAvailability::Unavailable { reason } => {
371 trace!("provider '{name}' is unavailable: {reason}");
372 Err(ProviderRegistryError::ProviderUnavailable {
373 name,
374 source: ProviderCreateError::unavailable(&reason),
375 })
376 }
377 }
378 }
379
380 /// Creates a boxed service using automatic provider selection.
381 ///
382 /// # Parameters
383 /// - `config`: Configuration passed to candidate providers.
384 ///
385 /// # Returns
386 /// Boxed service created by the highest-priority usable provider.
387 ///
388 /// # Errors
389 /// Returns [`ProviderRegistryError::EmptyRegistry`] when the registry has no
390 /// providers, or [`ProviderRegistryError::NoAvailableProvider`] when all
391 /// automatic candidates fail.
392 #[inline]
393 pub fn create_auto_box(
394 &self,
395 config: &Spec::Config,
396 ) -> Result<Box<Spec::Service>, ProviderRegistryError> {
397 self.create_selected_box(&ProviderSelection::Auto, config)
398 }
399
400 /// Creates an atomically shared service using automatic provider selection.
401 ///
402 /// # Parameters
403 /// - `config`: Configuration passed to candidate providers.
404 ///
405 /// # Returns
406 /// Atomically shared service created by the highest-priority usable provider.
407 ///
408 /// # Errors
409 /// Returns [`ProviderRegistryError::EmptyRegistry`] when the registry has no
410 /// providers, or [`ProviderRegistryError::NoAvailableProvider`] when all
411 /// automatic candidates fail.
412 #[inline]
413 pub fn create_auto_arc(
414 &self,
415 config: &Spec::Config,
416 ) -> Result<Arc<Spec::Service>, ProviderRegistryError> {
417 self.create_selected_arc(&ProviderSelection::Auto, config)
418 }
419
420 /// Creates a locally shared service using automatic provider selection.
421 ///
422 /// # Parameters
423 /// - `config`: Configuration passed to candidate providers.
424 ///
425 /// # Returns
426 /// Locally shared service created by the highest-priority usable provider.
427 ///
428 /// # Errors
429 /// Returns [`ProviderRegistryError::EmptyRegistry`] when the registry has no
430 /// providers, or [`ProviderRegistryError::NoAvailableProvider`] when all
431 /// automatic candidates fail.
432 #[inline]
433 pub fn create_auto_rc(
434 &self,
435 config: &Spec::Config,
436 ) -> Result<Rc<Spec::Service>, ProviderRegistryError> {
437 self.create_selected_rc(&ProviderSelection::Auto, config)
438 }
439
440 /// Creates a boxed service from explicit provider selection.
441 ///
442 /// Automatic selection tries all registered providers ordered by descending
443 /// priority and then by provider id. Named selection tries the primary
444 /// provider followed by fallbacks in order. Selection stops at the first
445 /// provider that can create a service.
446 ///
447 /// # Parameters
448 /// - `selection`: Provider selection policy.
449 /// - `config`: Configuration passed to candidate providers.
450 ///
451 /// # Returns
452 /// Boxed service created by the first successful provider candidate.
453 ///
454 /// # Errors
455 /// Returns [`ProviderRegistryError::DuplicateProviderCandidate`] when a
456 /// named selection repeats a candidate name,
457 /// [`ProviderRegistryError::EmptyRegistry`] when the registry has no providers, or
458 /// [`ProviderRegistryError::NoAvailableProvider`] when every candidate is
459 /// unknown, unavailable, or fails during creation.
460 #[inline]
461 pub fn create_selected_box(
462 &self,
463 selection: &ProviderSelection,
464 config: &Spec::Config,
465 ) -> Result<Box<Spec::Service>, ProviderRegistryError> {
466 self.create_selected_with(selection, config, |provider, config| {
467 provider.create_box(config)
468 })
469 }
470
471 /// Creates an atomically shared service from explicit provider selection.
472 ///
473 /// Automatic selection tries all registered providers ordered by descending
474 /// priority and then by provider id. Named selection tries the primary
475 /// provider followed by fallbacks in order. Selection stops at the first
476 /// provider that can create a service.
477 ///
478 /// # Parameters
479 /// - `selection`: Provider selection policy.
480 /// - `config`: Configuration passed to candidate providers.
481 ///
482 /// # Returns
483 /// Atomically shared service created by the first successful provider
484 /// candidate.
485 ///
486 /// # Errors
487 /// Returns [`ProviderRegistryError::DuplicateProviderCandidate`] when a
488 /// named selection repeats a candidate name,
489 /// [`ProviderRegistryError::EmptyRegistry`] when the registry has no providers, or
490 /// [`ProviderRegistryError::NoAvailableProvider`] when every candidate is
491 /// unknown, unavailable, or fails during creation.
492 #[inline]
493 pub fn create_selected_arc(
494 &self,
495 selection: &ProviderSelection,
496 config: &Spec::Config,
497 ) -> Result<Arc<Spec::Service>, ProviderRegistryError> {
498 self.create_selected_with(selection, config, |provider, config| {
499 provider.create_arc(config)
500 })
501 }
502
503 /// Creates a locally shared service from explicit provider selection.
504 ///
505 /// Automatic selection tries all registered providers ordered by descending
506 /// priority and then by provider id. Named selection tries the primary
507 /// provider followed by fallbacks in order. Selection stops at the first
508 /// provider that can create a service.
509 ///
510 /// # Parameters
511 /// - `selection`: Provider selection policy.
512 /// - `config`: Configuration passed to candidate providers.
513 ///
514 /// # Returns
515 /// Locally shared service created by the first successful provider
516 /// candidate.
517 ///
518 /// # Errors
519 /// Returns [`ProviderRegistryError::DuplicateProviderCandidate`] when a
520 /// named selection repeats a candidate name,
521 /// [`ProviderRegistryError::EmptyRegistry`] when the registry has no providers, or
522 /// [`ProviderRegistryError::NoAvailableProvider`] when every candidate is
523 /// unknown, unavailable, or fails during creation.
524 #[inline]
525 pub fn create_selected_rc(
526 &self,
527 selection: &ProviderSelection,
528 config: &Spec::Config,
529 ) -> Result<Rc<Spec::Service>, ProviderRegistryError> {
530 self.create_selected_with(selection, config, |provider, config| {
531 provider.create_rc(config)
532 })
533 }
534
535 /// Creates a service handle from explicit provider selection.
536 ///
537 /// # Parameters
538 /// - `selection`: Provider selection policy.
539 /// - `config`: Configuration passed to candidate providers.
540 /// - `create`: Provider factory method used to create the handle.
541 ///
542 /// # Returns
543 /// Service handle created by the first successful provider candidate.
544 ///
545 /// # Errors
546 /// Returns [`ProviderRegistryError::DuplicateProviderCandidate`] when a
547 /// named selection repeats a candidate name,
548 /// [`ProviderRegistryError::EmptyRegistry`] when the registry has no providers, or
549 /// [`ProviderRegistryError::NoAvailableProvider`] when every candidate is
550 /// unknown, unavailable, or fails during creation.
551 fn create_selected_with<Handle, Create>(
552 &self,
553 selection: &ProviderSelection,
554 config: &Spec::Config,
555 create: Create,
556 ) -> Result<Handle, ProviderRegistryError>
557 where
558 Create:
559 Fn(&dyn ServiceProvider<Spec>, &Spec::Config) -> Result<Handle, ProviderCreateError>,
560 {
561 selection.validate_unique_names()?;
562 if self.providers.is_empty() {
563 trace!("provider selection failed because registry is empty");
564 return Err(ProviderRegistryError::EmptyRegistry);
565 }
566 match selection {
567 ProviderSelection::Auto => {
568 trace!(
569 "automatic provider selection prepared {} candidate(s)",
570 self.auto_candidates().len(),
571 );
572 self.create_from_candidates_with(self.auto_candidates().iter(), config, &create)
573 }
574 ProviderSelection::Named { primary, fallbacks } => {
575 trace!(
576 "named provider selection will try primary '{}' with {} fallback(s)",
577 primary,
578 fallbacks.len(),
579 );
580 self.create_from_candidates_with(
581 std::iter::once(primary).chain(fallbacks.iter()),
582 config,
583 &create,
584 )
585 }
586 }
587 }
588
589 /// Creates a service handle by trying the supplied candidates in order.
590 ///
591 /// # Parameters
592 /// - `candidates`: Candidate provider names to try.
593 /// - `config`: Configuration passed to candidate providers.
594 /// - `create`: Provider factory method used to create the handle.
595 ///
596 /// # Returns
597 /// Service handle created by the first successful candidate.
598 ///
599 /// # Errors
600 /// Returns [`ProviderRegistryError::NoAvailableProvider`] when every
601 /// candidate is unknown, unavailable, or fails during creation. Candidate
602 /// names that resolve to a provider already tried earlier in the same
603 /// selection are skipped.
604 fn create_from_candidates_with<'a, I, Handle, Create>(
605 &self,
606 candidates: I,
607 config: &Spec::Config,
608 create: &Create,
609 ) -> Result<Handle, ProviderRegistryError>
610 where
611 I: IntoIterator<Item = &'a ProviderName>,
612 Create:
613 Fn(&dyn ServiceProvider<Spec>, &Spec::Config) -> Result<Handle, ProviderCreateError>,
614 {
615 let mut failures = Vec::new();
616 let mut tried_provider_indices = HashSet::new();
617 for candidate in candidates {
618 if let Some(provider_index) = self.index.get(candidate).copied()
619 && !tried_provider_indices.insert(provider_index)
620 {
621 trace!(
622 "provider candidate '{candidate}' resolves to an already tried provider; skipping",
623 );
624 continue;
625 }
626 match self.create_from_candidate_with(candidate, config, create) {
627 Ok(service) => {
628 debug!("provider candidate '{candidate}' created service");
629 return Ok(service);
630 }
631 Err(failure) => {
632 trace!("provider candidate failed: {failure}");
633 failures.push(failure);
634 }
635 }
636 }
637 trace!(
638 "provider selection exhausted all candidates with {} failure(s)",
639 failures.len(),
640 );
641 Err(ProviderRegistryError::NoAvailableProvider { failures })
642 }
643
644 /// Creates a service handle from one normalized candidate name.
645 ///
646 /// # Parameters
647 /// - `candidate`: Normalized provider id or alias.
648 /// - `config`: Configuration passed to the provider.
649 /// - `create`: Provider factory method used to create the handle.
650 ///
651 /// # Returns
652 /// Service handle created by the provider.
653 ///
654 /// # Errors
655 /// Returns [`ProviderFailure`] when the candidate is unknown, unavailable,
656 /// or fails during service creation.
657 fn create_from_candidate_with<Handle, Create>(
658 &self,
659 candidate: &ProviderName,
660 config: &Spec::Config,
661 create: &Create,
662 ) -> Result<Handle, ProviderFailure>
663 where
664 Create:
665 Fn(&dyn ServiceProvider<Spec>, &Spec::Config) -> Result<Handle, ProviderCreateError>,
666 {
667 let Some(entry) = self.find_entry_by_name(candidate) else {
668 trace!("provider candidate '{candidate}' is unknown");
669 return Err(ProviderFailure::unknown_name(candidate.clone()));
670 };
671 match entry.provider.availability(config) {
672 ProviderAvailability::Available => create(entry.provider.as_ref(), config)
673 .map_err(|error| failure_from_create_error(candidate.clone(), error)),
674 ProviderAvailability::Unavailable { reason } => {
675 trace!("provider candidate '{candidate}' is unavailable: {reason}");
676 Err(ProviderFailure::unavailable_name(
677 candidate.clone(),
678 &reason,
679 ))
680 }
681 }
682 }
683
684 /// Validates that a descriptor does not conflict with existing entries.
685 ///
686 /// # Parameters
687 /// - `descriptor`: Descriptor to validate.
688 ///
689 /// # Errors
690 /// Returns [`ProviderRegistryError::DuplicateProviderName`] when the
691 /// descriptor contains duplicate names or conflicts with an existing name.
692 fn validate_descriptor(
693 &self,
694 descriptor: &ProviderDescriptor,
695 ) -> Result<(), ProviderRegistryError> {
696 let mut local_names = HashSet::with_capacity(descriptor.aliases().len() + 1);
697 for name in descriptor.names() {
698 if !local_names.insert(name.clone()) || self.index.contains_key(name) {
699 return Err(ProviderRegistryError::DuplicateProviderName { name: name.clone() });
700 }
701 }
702 Ok(())
703 }
704
705 /// Finds a provider entry by a normalized provider name.
706 ///
707 /// # Parameters
708 /// - `name`: Normalized provider id or alias.
709 ///
710 /// # Returns
711 /// Matching provider entry, or `None` when no provider matches.
712 fn find_entry_by_name(&self, name: &ProviderName) -> Option<&ProviderEntry<Spec>> {
713 self.index
714 .get(name)
715 .and_then(|provider_index| self.providers.get(*provider_index))
716 }
717
718 /// Gets cached automatic provider candidates.
719 ///
720 /// # Returns
721 /// Provider ids ordered by descending priority and then ascending id.
722 fn auto_candidates(&self) -> &[ProviderName] {
723 &self.auto_candidates
724 }
725
726 /// Rebuilds cached automatic provider candidates.
727 fn rebuild_auto_candidates(&mut self) {
728 let mut provider_indices: Vec<usize> = (0..self.providers.len()).collect();
729 provider_indices.sort_by(|left, right| {
730 let left_descriptor = &self.providers[*left].descriptor;
731 let right_descriptor = &self.providers[*right].descriptor;
732 right_descriptor
733 .priority()
734 .cmp(&left_descriptor.priority())
735 .then_with(|| left_descriptor.id().cmp(right_descriptor.id()))
736 });
737 self.auto_candidates = provider_indices
738 .into_iter()
739 .map(|provider_index| self.providers[provider_index].descriptor.id().clone())
740 .collect();
741 }
742}
743
744impl<Spec> Clone for ProviderRegistry<Spec>
745where
746 Spec: ServiceSpec + 'static,
747{
748 /// Clones the provider list while sharing provider instances.
749 #[inline]
750 fn clone(&self) -> Self {
751 Self {
752 providers: self.providers.clone(),
753 index: self.index.clone(),
754 auto_candidates: self.auto_candidates.clone(),
755 marker: PhantomData,
756 }
757 }
758}
759
760impl<Spec> Clone for ProviderEntry<Spec>
761where
762 Spec: ServiceSpec + 'static,
763{
764 /// Clones one provider entry while sharing the provider instance.
765 #[inline]
766 fn clone(&self) -> Self {
767 Self {
768 descriptor: self.descriptor.clone(),
769 provider: self.provider.clone(),
770 }
771 }
772}
773
774impl<Spec> Default for ProviderRegistry<Spec>
775where
776 Spec: ServiceSpec + 'static,
777{
778 /// Creates an empty provider registry.
779 #[inline]
780 fn default() -> Self {
781 Self {
782 providers: Vec::new(),
783 index: HashMap::new(),
784 auto_candidates: Vec::new(),
785 marker: PhantomData,
786 }
787 }
788}
789
790/// Converts a provider creation error into a registry error.
791///
792/// # Parameters
793/// - `name`: Provider name being created.
794/// - `error`: Provider creation error.
795///
796/// # Returns
797/// Registry error with provider-name context.
798fn registry_error_from_create_error(
799 name: ProviderName,
800 error: ProviderCreateError,
801) -> ProviderRegistryError {
802 if error.is_unavailable() {
803 ProviderRegistryError::ProviderUnavailable {
804 name,
805 source: error,
806 }
807 } else {
808 ProviderRegistryError::ProviderCreate {
809 name,
810 source: error,
811 }
812 }
813}
814
815/// Converts a provider creation error into a candidate failure.
816///
817/// # Parameters
818/// - `name`: Candidate provider name.
819/// - `error`: Provider creation error.
820///
821/// # Returns
822/// Candidate failure with provider-name context.
823fn failure_from_create_error(name: ProviderName, error: ProviderCreateError) -> ProviderFailure {
824 if error.is_unavailable() {
825 ProviderFailure::unavailable_error(name, error)
826 } else {
827 ProviderFailure::create_failed_error(name, error)
828 }
829}