type_registry/logical/
index.rs

1use std::any::{type_name, TypeId};
2use std::collections::HashMap;
3use std::ops::ControlFlow;
4use crate::logical::registration_id::RegistrationId;
5use crate::logical::registry::Registry;
6use crate::logical::registry_entry::RegistryEntry;
7use crate::raw::{RegistryEntry as RawRegistryEntry};
8
9/// A static index over a [registry](Registry).
10pub trait Index<R: Registry + ?Sized>: 'static {
11    /// The type used to store the index.
12    type Storage: 'static
13        + Sync
14        + Send;
15
16    /// Allocates the storage (initially empty).
17    fn allocate() -> Self::Storage;
18
19    /// Inserts a registration into the index. The return value indicates whether to continue
20    /// building the index or to early-abort.
21    fn associate(
22        storage: &mut Self::Storage,
23        id: RegistrationId<R>,
24        entry: RegistryEntry<R>
25    ) -> ControlFlow<()>;
26}
27
28impl<R: Registry + ?Sized> Index<R> for RawRegistryEntry {
29    type Storage = HashMap<TypeId, RegistrationId<R>>;
30
31    fn allocate() -> Self::Storage {
32        HashMap::new()
33    }
34
35    fn associate(
36        storage: &mut Self::Storage,
37        id: RegistrationId<R>,
38        entry: RegistryEntry<R>
39    ) -> ControlFlow<()> {
40        if storage.insert(entry.raw().type_id(), id).is_some() {
41            let registry = type_name::<R>();
42            let name = entry.raw().type_name();
43            panic!("duplicate '{registry}' registration for '{name}'")
44        };
45        ControlFlow::Continue(())
46    }
47}