intuicio_core/
registry.rs

1use crate::{
2    function::{Function, FunctionHandle, FunctionQuery},
3    object::Object,
4    types::{Type, TypeHandle, TypeQuery, struct_type::NativeStructBuilder},
5};
6use intuicio_data::{
7    managed::{DynamicManaged, DynamicManagedLazy, DynamicManagedRef, DynamicManagedRefMut},
8    managed_box::DynamicManagedBox,
9};
10use std::{
11    collections::BTreeMap,
12    sync::{Arc, RwLock},
13};
14
15pub type RegistryHandle = Arc<Registry>;
16
17#[derive(Debug, Default)]
18pub struct Registry {
19    functions: Vec<FunctionHandle>,
20    types: Vec<TypeHandle>,
21    pub index_capacity: usize,
22    pub use_indexing_threshold: usize,
23    functions_index: RwLock<BTreeMap<u64, FunctionHandle>>,
24    types_index: RwLock<BTreeMap<u64, TypeHandle>>,
25}
26
27impl Clone for Registry {
28    fn clone(&self) -> Self {
29        Self {
30            functions: self.functions.clone(),
31            types: self.types.clone(),
32            index_capacity: self.index_capacity,
33            use_indexing_threshold: self.use_indexing_threshold,
34            functions_index: RwLock::new(
35                self.functions_index
36                    .read()
37                    .ok()
38                    .map(|items| items.clone())
39                    .unwrap_or_default(),
40            ),
41            types_index: RwLock::new(
42                self.types_index
43                    .read()
44                    .ok()
45                    .map(|items| items.clone())
46                    .unwrap_or_default(),
47            ),
48        }
49    }
50}
51
52impl Registry {
53    pub fn with_basic_types(self) -> Self {
54        self.with_type(NativeStructBuilder::new::<()>().build())
55            .with_type(NativeStructBuilder::new::<bool>().build())
56            .with_type(NativeStructBuilder::new::<i8>().build())
57            .with_type(NativeStructBuilder::new::<i16>().build())
58            .with_type(NativeStructBuilder::new::<i32>().build())
59            .with_type(NativeStructBuilder::new::<i64>().build())
60            .with_type(NativeStructBuilder::new::<i128>().build())
61            .with_type(NativeStructBuilder::new::<isize>().build())
62            .with_type(NativeStructBuilder::new::<u8>().build())
63            .with_type(NativeStructBuilder::new::<u16>().build())
64            .with_type(NativeStructBuilder::new::<u32>().build())
65            .with_type(NativeStructBuilder::new::<u64>().build())
66            .with_type(NativeStructBuilder::new::<u128>().build())
67            .with_type(NativeStructBuilder::new::<usize>().build())
68            .with_type(NativeStructBuilder::new::<f32>().build())
69            .with_type(NativeStructBuilder::new::<f64>().build())
70            .with_type(NativeStructBuilder::new::<char>().build())
71            .with_type(NativeStructBuilder::new_named::<String>("String").build())
72    }
73
74    pub fn with_erased_types(self) -> Self {
75        self.with_type(
76            NativeStructBuilder::new_named_uninitialized::<DynamicManaged>("DynamicManaged")
77                .build(),
78        )
79        .with_type(
80            NativeStructBuilder::new_named_uninitialized::<DynamicManagedLazy>(
81                "DynamicManagedLazy",
82            )
83            .build(),
84        )
85        .with_type(
86            NativeStructBuilder::new_named_uninitialized::<DynamicManagedRef>("DynamicManagedRef")
87                .build(),
88        )
89        .with_type(
90            NativeStructBuilder::new_named_uninitialized::<DynamicManagedRefMut>(
91                "DynamicManagedRefMut",
92            )
93            .build(),
94        )
95        .with_type(
96            NativeStructBuilder::new_named_uninitialized::<DynamicManagedBox>("DynamicManagedBox")
97                .build(),
98        )
99        .with_type(NativeStructBuilder::new_named_uninitialized::<Object>("Object").build())
100    }
101
102    pub fn with_index_capacity(mut self, capacity: usize) -> Self {
103        self.index_capacity = capacity;
104        self
105    }
106
107    pub fn with_max_index_capacity(mut self) -> Self {
108        self.index_capacity = usize::MAX;
109        self
110    }
111
112    pub fn with_use_indexing_threshold(mut self, threshold: usize) -> Self {
113        self.use_indexing_threshold = threshold;
114        self
115    }
116
117    pub fn with_install(mut self, f: impl FnOnce(&mut Self)) -> Self {
118        self.install(f);
119        self
120    }
121
122    pub fn with_function(mut self, function: Function) -> Self {
123        self.add_function(function);
124        self
125    }
126
127    pub fn with_type(mut self, type_: impl Into<Type>) -> Self {
128        self.add_type(type_);
129        self
130    }
131
132    pub fn install(&mut self, f: impl FnOnce(&mut Self)) {
133        f(self);
134    }
135
136    pub fn add_function_handle(&mut self, function_handle: FunctionHandle) {
137        if !self
138            .functions
139            .iter()
140            .any(|handle| handle.signature() == function_handle.signature())
141        {
142            self.functions.push(function_handle);
143        }
144    }
145
146    pub fn add_function(&mut self, function: Function) -> FunctionHandle {
147        if let Some(handle) = self
148            .functions
149            .iter()
150            .find(|handle| handle.signature() == function.signature())
151        {
152            handle.clone()
153        } else {
154            let handle = FunctionHandle::new(function);
155            self.functions.push(handle.clone());
156            handle
157        }
158    }
159
160    pub fn remove_function(&mut self, function_handle: FunctionHandle) {
161        if let Some(position) = self
162            .functions
163            .iter()
164            .position(|handle| handle.signature() == function_handle.signature())
165        {
166            self.functions.swap_remove(position);
167        }
168    }
169
170    pub fn remove_functions(&mut self, query: FunctionQuery) {
171        while let Some(position) = self
172            .functions
173            .iter()
174            .position(|handle| query.is_valid(handle.signature()))
175        {
176            self.functions.swap_remove(position);
177        }
178    }
179
180    pub fn functions(&self) -> impl Iterator<Item = &FunctionHandle> {
181        self.functions.iter()
182    }
183
184    pub fn find_functions<'a>(
185        &'a self,
186        query: FunctionQuery<'a>,
187    ) -> impl Iterator<Item = FunctionHandle> + 'a {
188        self.functions
189            .iter()
190            .filter(move |handle| query.is_valid(handle.signature()))
191            .cloned()
192    }
193
194    pub fn find_function<'a>(&'a self, query: FunctionQuery<'a>) -> Option<FunctionHandle> {
195        if self.index_capacity == 0 || self.functions.len() < self.use_indexing_threshold {
196            self.find_functions(query).next()
197        } else if let Ok(mut index) = self.functions_index.try_write() {
198            let hash = query.as_hash();
199            if let Some(found) = index.get(&hash) {
200                Some(found.clone())
201            } else if let Some(found) = self.find_functions(query).next() {
202                for _ in 0..(index.len().saturating_sub(self.index_capacity)) {
203                    if let Some(hash) = index.keys().next().copied() {
204                        index.remove(&hash);
205                    }
206                }
207                index.insert(hash, found.clone());
208                Some(found)
209            } else {
210                None
211            }
212        } else {
213            self.find_functions(query).next()
214        }
215    }
216
217    pub fn add_type_handle(&mut self, type_handle: TypeHandle) {
218        if !self
219            .types
220            .iter()
221            .any(|handle| handle.as_ref() == type_handle.as_ref())
222        {
223            self.types.push(type_handle);
224        }
225    }
226
227    pub fn add_type(&mut self, type_: impl Into<Type>) -> TypeHandle {
228        let type_ = type_.into();
229        if let Some(handle) = self.types.iter().find(|handle| handle.as_ref() == &type_) {
230            handle.clone()
231        } else {
232            let handle = TypeHandle::new(type_);
233            self.types.push(handle.clone());
234            handle
235        }
236    }
237
238    pub fn remove_type(&mut self, type_handle: TypeHandle) {
239        if let Some(position) = self.types.iter().position(|handle| handle == &type_handle) {
240            self.types.swap_remove(position);
241        }
242    }
243
244    pub fn remove_types(&mut self, query: TypeQuery) {
245        while let Some(position) = self.types.iter().position(|handle| query.is_valid(handle)) {
246            self.types.swap_remove(position);
247        }
248    }
249
250    pub fn types(&self) -> impl Iterator<Item = &TypeHandle> {
251        self.types.iter()
252    }
253
254    pub fn find_types<'a>(&'a self, query: TypeQuery<'a>) -> impl Iterator<Item = TypeHandle> + 'a {
255        self.types
256            .iter()
257            .filter(move |handle| query.is_valid(handle))
258            .cloned()
259    }
260
261    pub fn find_type<'a>(&'a self, query: TypeQuery<'a>) -> Option<TypeHandle> {
262        if self.index_capacity == 0 || self.types.len() < self.use_indexing_threshold {
263            self.find_types(query).next()
264        } else if let Ok(mut index) = self.types_index.try_write() {
265            let hash = query.as_hash();
266            if let Some(found) = index.get(&hash) {
267                Some(found.clone())
268            } else if let Some(found) = self.find_types(query).next() {
269                for _ in 0..(index.len().saturating_sub(self.index_capacity)) {
270                    if let Some(hash) = index.keys().next().copied() {
271                        index.remove(&hash);
272                    }
273                }
274                index.insert(hash, found.clone());
275                Some(found)
276            } else {
277                None
278            }
279        } else {
280            self.find_types(query).next()
281        }
282    }
283}
284
285#[cfg(test)]
286mod tests {
287    use super::*;
288
289    #[test]
290    fn test_async() {
291        fn is_async<T: Send + Sync>() {}
292
293        is_async::<Registry>();
294    }
295}