type_registry/logical/
registry_ext.rs1use std::any::Any;
2use std::ops::ControlFlow;
3use std::sync::OnceLock;
4use generic_static::StaticTypeMap;
5use crate::logical::index::Index;
6use crate::logical::Iter;
7use crate::logical::registry::Registry;
8
9pub trait RegistryExt: Registry {
11 fn iter() -> Iter<Self>;
13
14 fn index<I: Index<Self>>() -> &'static I::Storage;
16}
17
18impl<R: Registry + ?Sized> RegistryExt for R {
19 fn iter() -> Iter<Self> {
20 Iter::new()
21 }
22
23 fn index<I: Index<Self>>() -> &'static I::Storage {
24 static STORAGE_TYPE_MAP: OnceLock<StaticTypeMap<Box<dyn Any + Send + Sync>>> = OnceLock::new();
25 let storage_type_map = STORAGE_TYPE_MAP.get_or_init(|| StaticTypeMap::new());
26
27 let any = storage_type_map.call_once::<(fn(R), I), _>(
28 || {
29 let mut storage = I::allocate();
30
31 for (id, entry) in R::iter() {
32 match I::associate(&mut storage, id, entry) {
33 ControlFlow::Continue(_) => continue,
34 ControlFlow::Break(_) => break
35 }
36 }
37
38 Box::new(storage)
39 }
40 );
41
42 any.downcast_ref().expect("index storage is associated to type")
43 }
44}