springtime_di/
component_registry.rs

1//! Functionality related to registering definitions of components. [ComponentInstanceProvider]s
2//! should create [Component] instances based on those definitions, which can be registered
3//! automatically or manually.
4
5pub mod conditional;
6
7use crate::component::{Component, ComponentDowncast, Injectable};
8use crate::component_registry::conditional::{
9    ComponentDefinitionRegistryFacade, ConditionMetadata, ContextFactory,
10};
11use crate::component_registry::internal::{
12    ComponentAliasDefinition, ComponentAliasRegisterer, ComponentDefinitionRegisterer,
13    TypedComponentDefinition,
14};
15use crate::component_registry::registry::NamedComponentDefinitionMap;
16use crate::instance_provider::{
17    CastFunction, ComponentInstanceAnyPtr, ComponentInstanceProvider,
18    ComponentInstanceProviderError,
19};
20use derive_more::Debug;
21#[cfg(feature = "async")]
22use futures::future::BoxFuture;
23use itertools::Itertools;
24#[cfg(test)]
25use mockall::automock;
26use rustc_hash::{FxHashMap, FxHashSet};
27use std::any::{type_name, TypeId};
28use thiserror::Error;
29
30#[cfg(not(feature = "async"))]
31pub type Constructor = fn(
32    instance_provider: &mut dyn ComponentInstanceProvider,
33) -> Result<ComponentInstanceAnyPtr, ComponentInstanceProviderError>;
34
35#[cfg(feature = "async")]
36pub type Constructor =
37    fn(
38        instance_provider: &mut (dyn ComponentInstanceProvider + Sync + Send),
39    ) -> BoxFuture<'_, Result<ComponentInstanceAnyPtr, ComponentInstanceProviderError>>;
40
41/// Error related to component registries.
42#[derive(Error, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
43pub enum ComponentDefinitionRegistryError {
44    #[error("Attempted to register a duplicated component with name: {0}")]
45    DuplicateComponentName(String),
46    #[error("Attempted to re-register a concrete component type: {0}")]
47    DuplicateComponentType(String),
48    #[error("Missing base component of type {target_type} for alias: {alias_type}")]
49    MissingBaseComponent {
50        alias_type: String,
51        target_type: String,
52    },
53    #[error(
54        "Registering a duplicate primary component of type {target_type} for alias: {alias_type}"
55    )]
56    DuplicatePrimaryComponent {
57        alias_type: String,
58        target_type: String,
59    },
60}
61
62/// Definition for a [Component] registered in a definition registry.
63#[derive(Clone, Debug)]
64pub struct ComponentDefinition {
65    /// Each component has at least one name, which can be used to request a specific instance.
66    /// Derive-based components have their name generated from type name by converting it to snake
67    /// case.
68    pub names: FxHashSet<String>,
69
70    /// With multiple components registered for a given type, one of them can be marked as primary
71    /// and returned when requesting a single instance.
72    pub is_primary: bool,
73
74    /// Which type of [Scope](crate::scope::Scope) to use when requesting given component. Please
75    /// see [scope](crate::scope) for details on scopes.
76    pub scope: String,
77
78    /// Concrete component type id. Since aliases can share definitions with their targets, there
79    /// can be a need to find out what is the leaf type.
80    pub resolved_type_id: TypeId,
81
82    /// Human-readable type name for reporting purposes.
83    pub resolved_type_name: String,
84
85    /// Constructor method for type-erased instances.
86    #[debug(skip)]
87    pub constructor: Constructor,
88
89    /// Cast function associated for given type. Please see the documentation for [CastFunction] for
90    /// details on usage.
91    #[debug(skip)]
92    pub cast: CastFunction,
93}
94
95/// Registration information for a [Component]. Please see [ComponentDefinition] for information
96/// about the meaning of the fields.
97#[derive(Clone, Debug)]
98pub struct ComponentMetadata {
99    pub names: FxHashSet<String>,
100
101    pub scope: String,
102
103    #[debug(skip)]
104    pub constructor: Constructor,
105
106    #[debug(skip)]
107    pub cast: CastFunction,
108}
109
110/// Registration information for an  alias for a [Component] registered in a definition registry.
111/// Please see [ComponentDefinition] for information about the meaning of the fields.
112#[derive(Clone, Debug)]
113pub struct ComponentAliasMetadata {
114    pub is_primary: bool,
115
116    pub scope: Option<String>,
117
118    #[debug(skip)]
119    pub cast: CastFunction,
120}
121
122/// A registry of component definitions which can be used when requesting instances via a
123/// [ComponentInstanceProvider].
124#[cfg_attr(test, automock)]
125pub trait ComponentDefinitionRegistry {
126    /// Adds a new definition for a given type. Note: handling of duplicate component names is
127    /// registry-dependent. Name is used for reporting purposes.
128    fn register_component(
129        &mut self,
130        target: TypeId,
131        target_name: &str,
132        metadata: &ComponentMetadata,
133    ) -> Result<(), ComponentDefinitionRegistryError>;
134
135    /// Adds an alias for a component of target type. This is useful when registering
136    /// `dyn Trait` as an alias for a given concrete type. If alias cannot by cast to target,
137    /// component creation will fail. Names are used for reporting purposes.
138    fn register_alias(
139        &mut self,
140        alias_type: TypeId,
141        target_type: TypeId,
142        alias_name: &str,
143        target_name: &str,
144        metadata: &ComponentAliasMetadata,
145    ) -> Result<(), ComponentDefinitionRegistryError>;
146
147    /// Returns all registered definitions for a given type.
148    fn components_by_type(&self, type_id: TypeId) -> Vec<ComponentDefinition>;
149
150    /// Returns a definition with given name.
151    fn component_by_name(&self, name: &str, type_id: TypeId) -> Option<ComponentDefinition>;
152
153    /// Returns primary component for a given type.
154    fn primary_component(&self, type_id: TypeId) -> Option<ComponentDefinition>;
155
156    /// Checks if given type is present in this registry.
157    fn is_registered(&self, type_id: TypeId) -> bool;
158
159    /// Checks if there's a definition with given name.
160    fn is_name_registered(&self, name: &str) -> bool;
161
162    /// Returns a copy of the whole registry as a map.
163    fn all_definitions(&self) -> FxHashMap<TypeId, Vec<ComponentDefinition>>;
164}
165
166/// Helper trait for [ComponentDefinitionRegistry] providing strongly-typed access.
167pub trait TypedComponentDefinitionRegistry {
168    /// Typesafe version of [ComponentDefinitionRegistry::register_component].
169    fn register_component_typed<T: Component>(
170        &mut self,
171        metadata: &ComponentMetadata,
172    ) -> Result<(), ComponentDefinitionRegistryError>;
173
174    /// Typesafe version of [ComponentDefinitionRegistry::register_alias].
175    fn register_alias_typed<Source: ComponentDowncast<Target> + ?Sized, Target: Component>(
176        &mut self,
177        metadata: &ComponentAliasMetadata,
178    ) -> Result<(), ComponentDefinitionRegistryError>;
179
180    /// Typesafe version of [ComponentDefinitionRegistry::components_by_type].
181    fn components_by_type_typed<T: Injectable + ?Sized>(&self) -> Vec<ComponentDefinition>;
182
183    /// Typesafe version of [ComponentDefinitionRegistry::primary_component].
184    fn primary_component_typed<T: Injectable + ?Sized>(&self) -> Option<ComponentDefinition>;
185
186    /// Typesafe version of [ComponentDefinitionRegistry::is_registered].
187    fn is_registered_typed<T: Injectable>(&self) -> bool;
188}
189
190impl<CDR: ComponentDefinitionRegistry + ?Sized> TypedComponentDefinitionRegistry for CDR {
191    #[inline]
192    fn register_component_typed<T: Component>(
193        &mut self,
194        metadata: &ComponentMetadata,
195    ) -> Result<(), ComponentDefinitionRegistryError> {
196        self.register_component(TypeId::of::<T>(), type_name::<T>(), metadata)
197    }
198
199    #[inline]
200    fn register_alias_typed<Source: ComponentDowncast<Target> + ?Sized, Target: Component>(
201        &mut self,
202        metadata: &ComponentAliasMetadata,
203    ) -> Result<(), ComponentDefinitionRegistryError> {
204        self.register_alias(
205            TypeId::of::<Source>(),
206            TypeId::of::<Target>(),
207            type_name::<Source>(),
208            type_name::<Target>(),
209            metadata,
210        )
211    }
212
213    #[inline]
214    fn components_by_type_typed<T: Injectable + ?Sized>(&self) -> Vec<ComponentDefinition> {
215        self.components_by_type(TypeId::of::<T>())
216    }
217
218    #[inline]
219    fn primary_component_typed<T: Injectable + ?Sized>(&self) -> Option<ComponentDefinition> {
220        self.primary_component(TypeId::of::<T>())
221    }
222
223    #[inline]
224    fn is_registered_typed<T: Injectable>(&self) -> bool {
225        self.is_registered(TypeId::of::<T>())
226    }
227}
228
229/// Registry of component definitions initialized from statically registered definitions.
230#[derive(Clone, Debug)]
231pub struct StaticComponentDefinitionRegistry {
232    definition_map: NamedComponentDefinitionMap,
233    allow_definition_overriding: bool,
234}
235
236impl StaticComponentDefinitionRegistry {
237    pub fn new<CF: ContextFactory>(
238        allow_definition_overriding: bool,
239        context_factory: &CF,
240    ) -> Result<Self, ComponentDefinitionRegistryError> {
241        let component_definitions: Vec<TypedComponentDefinition> =
242            inventory::iter::<ComponentDefinitionRegisterer>
243                .into_iter()
244                .map(|registerer| (registerer.register)())
245                .collect_vec();
246
247        let alias_definitions: Vec<ComponentAliasDefinition> =
248            inventory::iter::<ComponentAliasRegisterer>
249                .into_iter()
250                .map(|registerer| (registerer.register)())
251                .collect_vec();
252
253        // components need to be registered in appropriate order to ensure dependencies are met:
254        // 1. unconditional components - they depend on nothing, so can go first
255        // 2. unconditional aliases for unconditional components - they only depend on the above
256        // 3. conditional components - they might depend on the above or each other
257        // 4. unconditional aliases for conditional components - they might depend on the above only
258        // 5. conditional aliases - they might depend on anything
259
260        let (definition_map, enabled_types) = Self::register_unconditional_components(
261            &component_definitions,
262            allow_definition_overriding,
263        )?;
264
265        let mut registry = Self {
266            definition_map,
267            allow_definition_overriding,
268        };
269
270        // register aliases for unconditionally registered components
271        registry.register_unconditional_aliases(&alias_definitions, &enabled_types)?;
272
273        registry.register_conditional_components_with_dependents(
274            component_definitions,
275            alias_definitions.clone(),
276            enabled_types,
277            context_factory,
278        )?;
279
280        Ok(registry)
281    }
282
283    fn register_conditional_components_with_dependents<CF: ContextFactory>(
284        &mut self,
285        component_definitions: Vec<TypedComponentDefinition>,
286        alias_definitions: Vec<ComponentAliasDefinition>,
287        mut enabled_types: FxHashSet<TypeId>,
288        context_factory: &CF,
289    ) -> Result<(), ComponentDefinitionRegistryError> {
290        if component_definitions.is_empty() && alias_definitions.is_empty() {
291            return Ok(());
292        }
293
294        let mut new_enabled_types = FxHashSet::default();
295
296        for (definition, condition) in component_definitions
297            .iter()
298            .filter_map(|definition| {
299                definition
300                    .condition
301                    .map(|condition| (definition, condition))
302            })
303            .sorted_by_key(|(definition, _)| -definition.priority)
304        {
305            if (condition)(
306                context_factory.create_context(self).as_ref(),
307                ConditionMetadata::Component {
308                    type_id: definition.target,
309                    metadata: &definition.metadata,
310                },
311            ) {
312                self.definition_map.try_register_component(
313                    definition.target,
314                    definition.target_name,
315                    &definition.metadata,
316                    self.allow_definition_overriding,
317                )?;
318
319                new_enabled_types.insert(definition.target);
320            }
321        }
322
323        self.register_unconditional_aliases(&alias_definitions, &new_enabled_types)?;
324
325        enabled_types.extend(new_enabled_types);
326
327        for (definition, condition) in alias_definitions
328            .iter()
329            .filter(|definition| enabled_types.contains(&definition.target_type))
330            .filter_map(|definition| {
331                definition
332                    .condition
333                    .map(|condition| (definition, condition))
334            })
335            .sorted_by_key(|(definition, _)| -definition.priority)
336        {
337            if (condition)(
338                context_factory.create_context(self).as_ref(),
339                ConditionMetadata::Alias {
340                    alias_type: definition.alias_type,
341                    target_type: definition.target_type,
342                    metadata: &definition.metadata,
343                },
344            ) {
345                self.definition_map.try_register_alias(
346                    definition.alias_type,
347                    definition.target_type,
348                    definition.alias_name,
349                    definition.target_name,
350                    &definition.metadata,
351                )?;
352            }
353        }
354
355        Ok(())
356    }
357
358    fn register_unconditional_components(
359        component_definitions: &[TypedComponentDefinition],
360        allow_definition_overriding: bool,
361    ) -> Result<(NamedComponentDefinitionMap, FxHashSet<TypeId>), ComponentDefinitionRegistryError>
362    {
363        let mut definition_map = NamedComponentDefinitionMap::default();
364        let mut enabled_types = FxHashSet::default();
365
366        for definition in component_definitions
367            .iter()
368            .filter(|definition| definition.condition.is_none())
369        {
370            definition_map.try_register_component(
371                definition.target,
372                definition.target_name,
373                &definition.metadata,
374                allow_definition_overriding,
375            )?;
376
377            enabled_types.insert(definition.target);
378        }
379
380        Ok((definition_map, enabled_types))
381    }
382
383    fn register_unconditional_aliases(
384        &mut self,
385        alias_definitions: &[ComponentAliasDefinition],
386        enabled_types: &FxHashSet<TypeId>,
387    ) -> Result<(), ComponentDefinitionRegistryError> {
388        for definition in alias_definitions.iter().filter(|definition| {
389            definition.condition.is_none() && enabled_types.contains(&definition.target_type)
390        }) {
391            self.definition_map.try_register_alias(
392                definition.alias_type,
393                definition.target_type,
394                definition.alias_name,
395                definition.target_name,
396                &definition.metadata,
397            )?;
398        }
399
400        Ok(())
401    }
402}
403
404impl ComponentDefinitionRegistry for StaticComponentDefinitionRegistry {
405    #[inline]
406    fn register_component(
407        &mut self,
408        target: TypeId,
409        target_name: &str,
410        metadata: &ComponentMetadata,
411    ) -> Result<(), ComponentDefinitionRegistryError> {
412        self.definition_map.try_register_component(
413            target,
414            target_name,
415            metadata,
416            self.allow_definition_overriding,
417        )
418    }
419
420    #[inline]
421    fn register_alias(
422        &mut self,
423        alias_type: TypeId,
424        target_type: TypeId,
425        alias_name: &str,
426        target_name: &str,
427        metadata: &ComponentAliasMetadata,
428    ) -> Result<(), ComponentDefinitionRegistryError> {
429        self.definition_map.try_register_alias(
430            alias_type,
431            target_type,
432            alias_name,
433            target_name,
434            metadata,
435        )
436    }
437
438    #[inline]
439    fn components_by_type(&self, type_id: TypeId) -> Vec<ComponentDefinition> {
440        self.definition_map.components_by_type(type_id)
441    }
442
443    #[inline]
444    fn component_by_name(&self, name: &str, type_id: TypeId) -> Option<ComponentDefinition> {
445        self.definition_map.component_by_name(name, type_id)
446    }
447
448    #[inline]
449    fn primary_component(&self, type_id: TypeId) -> Option<ComponentDefinition> {
450        self.definition_map.primary_component(type_id)
451    }
452
453    #[inline]
454    fn is_registered(&self, type_id: TypeId) -> bool {
455        <Self as ComponentDefinitionRegistryFacade>::is_registered(self, type_id)
456    }
457
458    #[inline]
459    fn is_name_registered(&self, name: &str) -> bool {
460        <Self as ComponentDefinitionRegistryFacade>::is_name_registered(self, name)
461    }
462
463    #[inline]
464    fn all_definitions(&self) -> FxHashMap<TypeId, Vec<ComponentDefinition>> {
465        self.definition_map.all_definitions()
466    }
467}
468
469impl ComponentDefinitionRegistryFacade for StaticComponentDefinitionRegistry {
470    #[inline]
471    fn is_registered(&self, target: TypeId) -> bool {
472        self.definition_map.is_registered(target)
473    }
474
475    #[inline]
476    fn is_name_registered(&self, name: &str) -> bool {
477        self.definition_map.is_name_registered(name)
478    }
479}
480
481mod registry {
482    use crate::component_registry::ComponentDefinitionRegistryError;
483    use crate::component_registry::{
484        ComponentAliasMetadata, ComponentDefinition, ComponentMetadata,
485    };
486    use rustc_hash::{FxHashMap, FxHashSet};
487    use std::any::TypeId;
488    use tracing::debug;
489
490    #[derive(Default, Clone, Debug)]
491    pub(super) struct NamedComponentDefinitionMap {
492        definitions: FxHashMap<TypeId, Vec<ComponentDefinition>>,
493        names: FxHashSet<String>,
494    }
495
496    impl NamedComponentDefinitionMap {
497        pub(super) fn component_by_name(
498            &self,
499            name: &str,
500            type_id: TypeId,
501        ) -> Option<ComponentDefinition> {
502            self.definitions
503                .get(&type_id)
504                .and_then(|definitions| {
505                    definitions
506                        .iter()
507                        .find(|definition| definition.names.contains(name))
508                })
509                .cloned()
510        }
511
512        pub(super) fn components_by_type(&self, type_id: TypeId) -> Vec<ComponentDefinition> {
513            self.definitions.get(&type_id).cloned().unwrap_or_default()
514        }
515
516        pub(super) fn primary_component(&self, type_id: TypeId) -> Option<ComponentDefinition> {
517            self.definitions.get(&type_id).and_then(|definitions| {
518                (if definitions.len() == 1 {
519                    definitions.first()
520                } else {
521                    definitions.iter().find(|definition| definition.is_primary)
522                })
523                .cloned()
524            })
525        }
526
527        pub(super) fn try_register_alias(
528            &mut self,
529            alias_type: TypeId,
530            target_type: TypeId,
531            alias_name: &str,
532            target_name: &str,
533            metadata: &ComponentAliasMetadata,
534        ) -> Result<(), ComponentDefinitionRegistryError> {
535            debug!(
536                ?alias_type,
537                alias_name,
538                ?target_type,
539                target_name,
540                "Registering new alias."
541            );
542
543            let mut target_definitions = self
544                .definitions
545                .get(&target_type)
546                .ok_or(ComponentDefinitionRegistryError::MissingBaseComponent {
547                    alias_type: alias_name.to_string(),
548                    target_type: target_name.to_string(),
549                })
550                .cloned()?;
551
552            // this should not be possible, since we don't allow removing definitions, but better
553            // be safe
554            if target_definitions.is_empty() {
555                return Err(ComponentDefinitionRegistryError::MissingBaseComponent {
556                    alias_type: alias_name.to_string(),
557                    target_type: target_name.to_string(),
558                });
559            }
560
561            // if we're registering a primary alias, there needs to be a single target
562            if metadata.is_primary && target_definitions.len() > 1 {
563                return Err(
564                    ComponentDefinitionRegistryError::DuplicatePrimaryComponent {
565                        alias_type: alias_name.to_string(),
566                        target_type: target_name.to_string(),
567                    },
568                );
569            }
570
571            // should run once due to above anyway
572            for definition in &mut target_definitions {
573                definition.is_primary = metadata.is_primary;
574                definition.cast = metadata.cast;
575
576                if let Some(scope) = &metadata.scope {
577                    definition.scope.clone_from(scope);
578                }
579            }
580
581            if let Some(alias_definitions) = self.definitions.get_mut(&alias_type) {
582                if metadata.is_primary
583                    && alias_definitions
584                        .iter()
585                        .any(|definition| definition.is_primary)
586                {
587                    return Err(
588                        ComponentDefinitionRegistryError::DuplicatePrimaryComponent {
589                            alias_type: alias_name.to_string(),
590                            target_type: target_name.to_string(),
591                        },
592                    );
593                }
594
595                alias_definitions.append(&mut target_definitions);
596            } else {
597                self.definitions.insert(alias_type, target_definitions);
598            }
599
600            Ok(())
601        }
602
603        pub(super) fn try_register_component(
604            &mut self,
605            target: TypeId,
606            target_name: &str,
607            metadata: &ComponentMetadata,
608            allow_definition_overriding: bool,
609        ) -> Result<(), ComponentDefinitionRegistryError> {
610            debug!(?target, target_name, "Registering new component.");
611
612            if !allow_definition_overriding {
613                if let Some(name) = metadata.names.iter().find_map(|name| {
614                    if self.names.contains(name) {
615                        Some(name.clone())
616                    } else {
617                        None
618                    }
619                }) {
620                    return Err(ComponentDefinitionRegistryError::DuplicateComponentName(
621                        name,
622                    ));
623                }
624            }
625
626            let definition = ComponentDefinition {
627                names: metadata.names.clone(),
628                is_primary: false,
629                scope: metadata.scope.clone(),
630                resolved_type_id: target,
631                resolved_type_name: target_name.to_string(),
632                constructor: metadata.constructor,
633                cast: metadata.cast,
634            };
635
636            let names = definition.names.clone();
637
638            if let Some(entries) = self.definitions.get_mut(&target) {
639                // concrete component types should not have multiple definitions
640                debug_assert!(entries.len() <= 1);
641
642                if !allow_definition_overriding && !entries.is_empty() {
643                    return Err(ComponentDefinitionRegistryError::DuplicateComponentType(
644                        target_name.to_string(),
645                    ));
646                }
647
648                entries
649                    .iter()
650                    .flat_map(|entry| entry.names.iter())
651                    .for_each(|name| {
652                        self.names.remove(name);
653                    });
654
655                *entries = vec![definition];
656            } else {
657                self.definitions.insert(target, vec![definition]);
658            }
659
660            self.names.extend(names);
661            Ok(())
662        }
663
664        #[inline]
665        pub(super) fn is_registered(&self, target: TypeId) -> bool {
666            self.definitions
667                .get(&target)
668                .map(|definitions| !definitions.is_empty())
669                .unwrap_or(false)
670        }
671
672        #[inline]
673        pub(super) fn is_name_registered(&self, name: &str) -> bool {
674            self.names.contains(name)
675        }
676
677        #[inline]
678        pub(super) fn all_definitions(&self) -> FxHashMap<TypeId, Vec<ComponentDefinition>> {
679            self.definitions.clone()
680        }
681    }
682
683    #[cfg(test)]
684    mod tests {
685        #[cfg(not(feature = "async"))]
686        mod sync {
687            use crate::component_registry::registry::NamedComponentDefinitionMap;
688            use crate::component_registry::{
689                ComponentAliasMetadata, ComponentDefinitionRegistryError, ComponentMetadata,
690            };
691            use crate::instance_provider::{
692                ComponentInstanceAnyPtr, ComponentInstanceProvider, ComponentInstanceProviderError,
693                ComponentInstancePtr,
694            };
695            use std::any::{Any, TypeId};
696
697            fn cast(
698                instance: ComponentInstanceAnyPtr,
699            ) -> Result<Box<dyn Any>, ComponentInstanceAnyPtr> {
700                Err(instance)
701            }
702
703            fn constructor(
704                _instance_provider: &mut dyn ComponentInstanceProvider,
705            ) -> Result<ComponentInstanceAnyPtr, ComponentInstanceProviderError> {
706                Ok(ComponentInstancePtr::new(0) as ComponentInstanceAnyPtr)
707            }
708
709            fn create_metadata() -> (ComponentMetadata, TypeId) {
710                (
711                    ComponentMetadata {
712                        names: ["name".to_string()].into_iter().collect(),
713                        scope: "".to_string(),
714                        constructor,
715                        cast,
716                    },
717                    TypeId::of::<i8>(),
718                )
719            }
720
721            #[test]
722            fn should_reject_primary_alias_for_ambiguous_target() {
723                let definition = ComponentMetadata {
724                    names: Default::default(),
725                    scope: "".to_string(),
726                    constructor,
727                    cast,
728                };
729                let alias_id_1 = TypeId::of::<u8>();
730                let alias_id_2 = TypeId::of::<u16>();
731                let target_id_1 = TypeId::of::<i16>();
732                let target_id_2 = TypeId::of::<u16>();
733
734                let mut registry = NamedComponentDefinitionMap::default();
735                registry
736                    .try_register_component(target_id_1, "", &definition, false)
737                    .unwrap();
738                registry
739                    .try_register_component(target_id_2, "", &definition, false)
740                    .unwrap();
741                registry
742                    .try_register_alias(
743                        alias_id_1,
744                        target_id_1,
745                        "",
746                        "",
747                        &ComponentAliasMetadata {
748                            is_primary: false,
749                            scope: None,
750                            cast,
751                        },
752                    )
753                    .unwrap();
754                registry
755                    .try_register_alias(
756                        alias_id_1,
757                        target_id_2,
758                        "",
759                        "",
760                        &ComponentAliasMetadata {
761                            is_primary: false,
762                            scope: None,
763                            cast,
764                        },
765                    )
766                    .unwrap();
767
768                assert!(matches!(
769                    registry
770                        .try_register_alias(
771                            alias_id_2,
772                            alias_id_1,
773                            "",
774                            "",
775                            &ComponentAliasMetadata {
776                                is_primary: true,
777                                scope: None,
778                                cast,
779                            },
780                        )
781                        .unwrap_err(),
782                    ComponentDefinitionRegistryError::DuplicatePrimaryComponent { .. }
783                ));
784            }
785
786            #[test]
787            fn should_register_definition() {
788                let (definition, id) = create_metadata();
789
790                let mut registry = NamedComponentDefinitionMap::default();
791                registry
792                    .try_register_component(id, "", &definition, false)
793                    .unwrap();
794
795                assert_eq!(registry.components_by_type(id)[0].names, definition.names);
796                assert_eq!(
797                    registry.component_by_name("name", id).unwrap().names,
798                    definition.names
799                );
800                assert!(registry.is_registered(id));
801                assert!(registry.is_name_registered("name"));
802            }
803
804            #[test]
805            fn should_not_register_duplicate_name() {
806                let (definition, id) = create_metadata();
807
808                let mut registry = NamedComponentDefinitionMap::default();
809                registry
810                    .try_register_component(id, "", &definition, false)
811                    .unwrap();
812
813                assert!(matches!(
814                    registry
815                        .try_register_component(id, "", &definition, false)
816                        .unwrap_err(),
817                    ComponentDefinitionRegistryError::DuplicateComponentName(..)
818                ));
819            }
820
821            #[test]
822            fn should_override_duplicate_name() {
823                let (definition, id) = create_metadata();
824
825                let mut registry = NamedComponentDefinitionMap::default();
826                registry
827                    .try_register_component(id, "", &definition, true)
828                    .unwrap();
829                registry
830                    .try_register_component(id, "", &definition, true)
831                    .unwrap();
832            }
833
834            #[test]
835            fn should_register_alias() {
836                let (definition, id) = create_metadata();
837                let alias_id = TypeId::of::<u8>();
838
839                let mut registry = NamedComponentDefinitionMap::default();
840                registry
841                    .try_register_component(id, "", &definition, false)
842                    .unwrap();
843                registry
844                    .try_register_alias(
845                        alias_id,
846                        id,
847                        "",
848                        "",
849                        &ComponentAliasMetadata {
850                            is_primary: false,
851                            scope: None,
852                            cast,
853                        },
854                    )
855                    .unwrap();
856
857                assert_eq!(
858                    registry.components_by_type(alias_id)[0].names,
859                    definition.names
860                );
861            }
862
863            #[test]
864            fn should_register_alias_scope() {
865                let (definition, id) = create_metadata();
866                let alias_id = TypeId::of::<u8>();
867
868                let mut registry = NamedComponentDefinitionMap::default();
869                registry
870                    .try_register_component(id, "", &definition, false)
871                    .unwrap();
872                registry
873                    .try_register_alias(
874                        alias_id,
875                        id,
876                        "",
877                        "",
878                        &ComponentAliasMetadata {
879                            is_primary: false,
880                            scope: Some("scope".to_string()),
881                            cast,
882                        },
883                    )
884                    .unwrap();
885
886                assert_eq!(registry.components_by_type(alias_id)[0].scope, "scope");
887            }
888
889            #[test]
890            fn should_reject_duplicate_primary_alias() {
891                let (definition, id) = create_metadata();
892                let alias_id = TypeId::of::<u8>();
893
894                let mut registry = NamedComponentDefinitionMap::default();
895                registry
896                    .try_register_component(id, "", &definition, false)
897                    .unwrap();
898                registry
899                    .try_register_alias(
900                        alias_id,
901                        id,
902                        "",
903                        "",
904                        &ComponentAliasMetadata {
905                            is_primary: true,
906                            scope: None,
907                            cast,
908                        },
909                    )
910                    .unwrap();
911
912                assert!(matches!(
913                    registry
914                        .try_register_alias(
915                            alias_id,
916                            id,
917                            "",
918                            "",
919                            &ComponentAliasMetadata {
920                                is_primary: true,
921                                scope: None,
922                                cast
923                            },
924                        )
925                        .unwrap_err(),
926                    ComponentDefinitionRegistryError::DuplicatePrimaryComponent { .. }
927                ));
928            }
929
930            #[test]
931            fn should_return_primary_single_definition() {
932                let (definition, id) = create_metadata();
933                let alias_id = TypeId::of::<u8>();
934
935                let mut registry = NamedComponentDefinitionMap::default();
936                registry
937                    .try_register_component(id, "", &definition, false)
938                    .unwrap();
939                registry
940                    .try_register_alias(
941                        alias_id,
942                        id,
943                        "",
944                        "",
945                        &ComponentAliasMetadata {
946                            is_primary: false,
947                            scope: None,
948                            cast,
949                        },
950                    )
951                    .unwrap();
952
953                assert!(registry.primary_component(alias_id).is_some());
954            }
955
956            #[test]
957            fn should_return_explicit_primary_definition() {
958                let (definition, id_1) = create_metadata();
959                let id_2 = TypeId::of::<u16>();
960                let alias_id = TypeId::of::<u8>();
961
962                let mut registry = NamedComponentDefinitionMap::default();
963                registry
964                    .try_register_component(id_1, "", &definition, false)
965                    .unwrap();
966                registry
967                    .try_register_component(id_2, "", &definition, true)
968                    .unwrap();
969                registry
970                    .try_register_alias(
971                        alias_id,
972                        id_1,
973                        "",
974                        "",
975                        &ComponentAliasMetadata {
976                            is_primary: false,
977                            scope: None,
978                            cast,
979                        },
980                    )
981                    .unwrap();
982                registry
983                    .try_register_alias(
984                        alias_id,
985                        id_2,
986                        "",
987                        "",
988                        &ComponentAliasMetadata {
989                            is_primary: true,
990                            scope: None,
991                            cast,
992                        },
993                    )
994                    .unwrap();
995
996                assert!(registry.primary_component(alias_id).is_some());
997            }
998
999            #[test]
1000            fn should_not_return_unknown_primary_definition() {
1001                let (definition, id_1) = create_metadata();
1002                let id_2 = TypeId::of::<u16>();
1003                let alias_id = TypeId::of::<u8>();
1004
1005                let mut registry = NamedComponentDefinitionMap::default();
1006                registry
1007                    .try_register_component(id_1, "", &definition, false)
1008                    .unwrap();
1009                registry
1010                    .try_register_component(id_2, "", &definition, true)
1011                    .unwrap();
1012                registry
1013                    .try_register_alias(
1014                        alias_id,
1015                        id_1,
1016                        "",
1017                        "",
1018                        &ComponentAliasMetadata {
1019                            is_primary: false,
1020                            scope: None,
1021                            cast,
1022                        },
1023                    )
1024                    .unwrap();
1025                registry
1026                    .try_register_alias(
1027                        alias_id,
1028                        id_2,
1029                        "",
1030                        "",
1031                        &ComponentAliasMetadata {
1032                            is_primary: false,
1033                            scope: None,
1034                            cast,
1035                        },
1036                    )
1037                    .unwrap();
1038
1039                assert!(registry.primary_component(alias_id).is_none());
1040            }
1041        }
1042    }
1043}
1044
1045#[doc(hidden)]
1046pub mod internal {
1047    use crate::component_registry::conditional::ComponentCondition;
1048    use crate::component_registry::{ComponentAliasMetadata, ComponentMetadata};
1049    use inventory::collect;
1050    pub use inventory::submit;
1051    use std::any::TypeId;
1052
1053    #[derive(Clone)]
1054    pub struct TypedComponentDefinition {
1055        pub target: TypeId,
1056        pub target_name: &'static str,
1057        pub condition: Option<ComponentCondition>,
1058        pub priority: i8,
1059        pub metadata: ComponentMetadata,
1060    }
1061
1062    pub struct ComponentDefinitionRegisterer {
1063        pub register: fn() -> TypedComponentDefinition,
1064    }
1065
1066    #[derive(Clone)]
1067    pub struct ComponentAliasDefinition {
1068        pub alias_type: TypeId,
1069        pub target_type: TypeId,
1070        pub alias_name: &'static str,
1071        pub target_name: &'static str,
1072        pub condition: Option<ComponentCondition>,
1073        pub priority: i8,
1074        pub metadata: ComponentAliasMetadata,
1075    }
1076
1077    pub struct ComponentAliasRegisterer {
1078        pub register: fn() -> ComponentAliasDefinition,
1079    }
1080
1081    collect!(ComponentDefinitionRegisterer);
1082    collect!(ComponentAliasRegisterer);
1083}
1084
1085#[cfg(test)]
1086//noinspection DuplicatedCode
1087mod tests {
1088    #[cfg(not(feature = "async"))]
1089    mod sync {
1090        use crate::component::{Component, ComponentDowncast, Injectable};
1091        use crate::component_registry::conditional::{
1092            ComponentDefinitionRegistryFacade, SimpleContextFactory,
1093        };
1094        use crate::component_registry::ComponentDefinitionRegistryError;
1095        use crate::component_registry::{
1096            ComponentDefinition, ComponentDefinitionRegistry, ComponentMetadata,
1097            StaticComponentDefinitionRegistry, TypedComponentDefinitionRegistry,
1098        };
1099        use crate::instance_provider::{
1100            ComponentInstanceAnyPtr, ComponentInstanceProvider, ComponentInstanceProviderError,
1101            ComponentInstancePtr,
1102        };
1103        use std::any::{type_name, Any, TypeId};
1104
1105        struct TestComponent;
1106
1107        impl Injectable for TestComponent {}
1108
1109        impl ComponentDowncast<TestComponent> for TestComponent {
1110            fn downcast(
1111                source: ComponentInstanceAnyPtr,
1112            ) -> Result<ComponentInstancePtr<Self>, ComponentInstanceAnyPtr> {
1113                source.downcast()
1114            }
1115        }
1116
1117        impl Component for TestComponent {
1118            fn create(
1119                _instance_provider: &mut dyn ComponentInstanceProvider,
1120            ) -> Result<Self, ComponentInstanceProviderError>
1121            where
1122                Self: Sized,
1123            {
1124                Ok(TestComponent)
1125            }
1126        }
1127
1128        fn test_constructor(
1129            instance_provider: &mut dyn ComponentInstanceProvider,
1130        ) -> Result<ComponentInstanceAnyPtr, ComponentInstanceProviderError> {
1131            TestComponent::create(instance_provider)
1132                .map(|p| ComponentInstancePtr::new(p) as ComponentInstanceAnyPtr)
1133        }
1134
1135        fn test_cast(
1136            instance: ComponentInstanceAnyPtr,
1137        ) -> Result<Box<dyn Any>, ComponentInstanceAnyPtr> {
1138            TestComponent::downcast(instance).map(|p| Box::new(p) as Box<dyn Any>)
1139        }
1140
1141        #[test]
1142        fn should_register_definition() {
1143            let mut registry =
1144                StaticComponentDefinitionRegistry::new(false, &SimpleContextFactory::default())
1145                    .unwrap();
1146            registry
1147                .register_component_typed::<TestComponent>(&ComponentMetadata {
1148                    names: ["a".to_string()].into_iter().collect(),
1149                    scope: "".to_string(),
1150                    constructor: test_constructor,
1151                    cast: test_cast,
1152                })
1153                .unwrap();
1154
1155            assert!(!registry
1156                .components_by_type_typed::<TestComponent>()
1157                .is_empty());
1158            assert!(TypedComponentDefinitionRegistry::is_registered_typed::<
1159                TestComponent,
1160            >(&registry));
1161            assert!(ComponentDefinitionRegistryFacade::is_registered(
1162                &registry,
1163                TypeId::of::<TestComponent>(),
1164            ));
1165            assert!(ComponentDefinitionRegistry::is_name_registered(
1166                &registry, "a",
1167            ));
1168        }
1169
1170        #[test]
1171        fn should_not_register_duplicate_name() {
1172            let definition = ComponentDefinition {
1173                names: ["name".to_string()].into_iter().collect(),
1174                is_primary: false,
1175                scope: "".to_string(),
1176                resolved_type_id: TypeId::of::<TestComponent>(),
1177                resolved_type_name: type_name::<TestComponent>().to_string(),
1178                constructor: test_constructor,
1179                cast: test_cast,
1180            };
1181
1182            let mut registry =
1183                StaticComponentDefinitionRegistry::new(false, &SimpleContextFactory::default())
1184                    .unwrap();
1185            registry
1186                .register_component_typed::<TestComponent>(&ComponentMetadata {
1187                    names: definition.names.clone(),
1188                    scope: "".to_string(),
1189                    constructor: test_constructor,
1190                    cast: test_cast,
1191                })
1192                .unwrap();
1193
1194            assert_eq!(
1195                registry
1196                    .register_component_typed::<TestComponent>(&ComponentMetadata {
1197                        names: definition.names,
1198                        scope: "".to_string(),
1199                        constructor: test_constructor,
1200                        cast: test_cast,
1201                    })
1202                    .unwrap_err(),
1203                ComponentDefinitionRegistryError::DuplicateComponentName("name".to_string())
1204            );
1205        }
1206
1207        #[test]
1208        fn should_override_duplicate_name() {
1209            let mut registry =
1210                StaticComponentDefinitionRegistry::new(true, &SimpleContextFactory::default())
1211                    .unwrap();
1212            registry
1213                .register_component_typed::<TestComponent>(&ComponentMetadata {
1214                    names: ["name".to_string()].into_iter().collect(),
1215                    scope: "".to_string(),
1216                    constructor: test_constructor,
1217                    cast: test_cast,
1218                })
1219                .unwrap();
1220            registry
1221                .register_component_typed::<TestComponent>(&ComponentMetadata {
1222                    names: ["name2".to_string()].into_iter().collect(),
1223                    scope: "".to_string(),
1224                    constructor: test_constructor,
1225                    cast: test_cast,
1226                })
1227                .unwrap();
1228
1229            registry
1230                .component_by_name("name2", TypeId::of::<TestComponent>())
1231                .unwrap();
1232        }
1233    }
1234}