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