1pub 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#[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#[derive(Clone, Debug)]
64pub struct ComponentDefinition {
65 pub names: FxHashSet<String>,
69
70 pub is_primary: bool,
73
74 pub scope: String,
77
78 pub resolved_type_id: TypeId,
81
82 pub resolved_type_name: String,
84
85 #[debug(skip)]
87 pub constructor: Constructor,
88
89 #[debug(skip)]
92 pub cast: CastFunction,
93}
94
95#[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#[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#[cfg_attr(test, automock)]
125pub trait ComponentDefinitionRegistry {
126 fn register_component(
129 &mut self,
130 target: TypeId,
131 target_name: &str,
132 metadata: &ComponentMetadata,
133 ) -> Result<(), ComponentDefinitionRegistryError>;
134
135 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 fn components_by_type(&self, type_id: TypeId) -> Vec<ComponentDefinition>;
149
150 fn component_by_name(&self, name: &str, type_id: TypeId) -> Option<ComponentDefinition>;
152
153 fn primary_component(&self, type_id: TypeId) -> Option<ComponentDefinition>;
155
156 fn is_registered(&self, type_id: TypeId) -> bool;
158
159 fn is_name_registered(&self, name: &str) -> bool;
161
162 fn all_definitions(&self) -> FxHashMap<TypeId, Vec<ComponentDefinition>>;
164}
165
166pub trait TypedComponentDefinitionRegistry {
168 fn register_component_typed<T: Component>(
170 &mut self,
171 metadata: &ComponentMetadata,
172 ) -> Result<(), ComponentDefinitionRegistryError>;
173
174 fn register_alias_typed<Source: ComponentDowncast<Target> + ?Sized, Target: Component>(
176 &mut self,
177 metadata: &ComponentAliasMetadata,
178 ) -> Result<(), ComponentDefinitionRegistryError>;
179
180 fn components_by_type_typed<T: Injectable + ?Sized>(&self) -> Vec<ComponentDefinition>;
182
183 fn primary_component_typed<T: Injectable + ?Sized>(&self) -> Option<ComponentDefinition>;
185
186 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#[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 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 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 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 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 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 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)]
1086mod 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 >(®istry));
1161 assert!(ComponentDefinitionRegistryFacade::is_registered(
1162 ®istry,
1163 TypeId::of::<TestComponent>(),
1164 ));
1165 assert!(ComponentDefinitionRegistry::is_name_registered(
1166 ®istry, "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}