dampen_core/handler/
mod.rs1use std::any::Any;
4use std::collections::{HashMap, HashSet};
5use std::sync::{Arc, RwLock};
6
7#[derive(Clone, Debug)]
9pub struct HandlerRegistry {
10 handlers: Arc<RwLock<HashMap<String, HandlerEntry>>>,
11}
12
13#[derive(Clone)]
15#[allow(clippy::type_complexity)]
16pub enum HandlerEntry {
17 Simple(Arc<dyn Fn(&mut dyn Any) + Send + Sync>),
19
20 WithValue(Arc<dyn Fn(&mut dyn Any, Box<dyn Any>) + Send + Sync>),
22
23 WithCommand(Arc<dyn Fn(&mut dyn Any) -> Box<dyn Any> + Send + Sync>),
25}
26
27impl std::fmt::Debug for HandlerEntry {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 match self {
30 HandlerEntry::Simple(_) => f.write_str("Simple(handler)"),
31 HandlerEntry::WithValue(_) => f.write_str("WithValue(handler)"),
32 HandlerEntry::WithCommand(_) => f.write_str("WithCommand(handler)"),
33 }
34 }
35}
36
37impl HandlerRegistry {
38 pub fn new() -> Self {
40 Self {
41 handlers: Arc::new(RwLock::new(HashMap::new())),
42 }
43 }
44
45 pub fn register_simple<F>(&self, name: &str, handler: F)
47 where
48 F: Fn(&mut dyn Any) + Send + Sync + 'static,
49 {
50 if let Ok(mut handlers) = self.handlers.write() {
51 handlers.insert(name.to_string(), HandlerEntry::Simple(Arc::new(handler)));
52 }
53 }
54
55 pub fn register_with_value<F>(&self, name: &str, handler: F)
57 where
58 F: Fn(&mut dyn Any, Box<dyn Any>) + Send + Sync + 'static,
59 {
60 if let Ok(mut handlers) = self.handlers.write() {
61 handlers.insert(name.to_string(), HandlerEntry::WithValue(Arc::new(handler)));
62 }
63 }
64
65 pub fn register_with_command<F>(&self, name: &str, handler: F)
67 where
68 F: Fn(&mut dyn Any) -> Box<dyn Any> + Send + Sync + 'static,
69 {
70 if let Ok(mut handlers) = self.handlers.write() {
71 handlers.insert(
72 name.to_string(),
73 HandlerEntry::WithCommand(Arc::new(handler)),
74 );
75 }
76 }
77
78 pub fn get(&self, name: &str) -> Option<HandlerEntry> {
80 self.handlers.read().ok()?.get(name).cloned()
81 }
82
83 pub fn dispatch(&self, handler_name: &str, model: &mut dyn Any, value: Option<String>) {
108 if let Some(entry) = self.get(handler_name) {
109 match entry {
110 HandlerEntry::Simple(h) => h(model),
111 HandlerEntry::WithValue(h) => {
112 let val = value.unwrap_or_default();
113 h(model, Box::new(val));
114 }
115 HandlerEntry::WithCommand(h) => {
116 h(model);
117 }
118 }
119 }
120 }
121
122 pub fn contains(&self, name: &str) -> bool {
124 if let Ok(handlers) = self.handlers.read() {
125 handlers.contains_key(name)
126 } else {
127 false
128 }
129 }
130}
131
132impl Default for HandlerRegistry {
133 fn default() -> Self {
134 Self::new()
135 }
136}
137
138#[derive(Debug, Clone, PartialEq)]
140pub struct HandlerSignature {
141 pub name: String,
143
144 pub param_type: Option<String>,
146
147 pub returns_command: bool,
149}
150
151#[derive(Debug, Clone)]
153pub struct HandlerCallGraph {
154 dependencies: HashMap<String, Vec<String>>,
156}
157
158impl HandlerCallGraph {
159 pub fn new() -> Self {
161 Self {
162 dependencies: HashMap::new(),
163 }
164 }
165
166 pub fn add_dependency(&mut self, from: &str, to: &str) {
168 self.dependencies
169 .entry(from.to_string())
170 .or_default()
171 .push(to.to_string());
172 }
173
174 pub fn would_create_cycle(&self, from: &str, to: &str) -> bool {
176 let mut visited = HashSet::new();
178 self.can_reach(to, from, &mut visited)
179 }
180
181 fn can_reach(&self, from: &str, to: &str, visited: &mut HashSet<String>) -> bool {
183 if from == to {
184 return true;
185 }
186
187 if visited.contains(from) {
188 return false;
189 }
190
191 visited.insert(from.to_string());
192
193 if let Some(deps) = self.dependencies.get(from) {
194 for dep in deps {
195 if self.can_reach(dep, to, visited) {
196 return true;
197 }
198 }
199 }
200
201 false
202 }
203
204 pub fn dependents_of(&self, handler: &str) -> Vec<String> {
206 self.dependencies
207 .iter()
208 .filter_map(|(k, v)| {
209 if v.contains(&handler.to_string()) {
210 Some(k.clone())
211 } else {
212 None
213 }
214 })
215 .collect()
216 }
217
218 pub fn detect_cycles(&self) -> Option<Vec<String>> {
220 let mut visited = HashSet::new();
221 let mut recursion_stack = HashSet::new();
222 let mut path = Vec::new();
223
224 for handler in self.dependencies.keys() {
225 if !visited.contains(handler) {
226 if let Some(cycle) =
227 self.dfs_detect_cycle(handler, &mut visited, &mut recursion_stack, &mut path)
228 {
229 return Some(cycle);
230 }
231 }
232 }
233
234 None
235 }
236
237 fn dfs_detect_cycle(
238 &self,
239 handler: &str,
240 visited: &mut HashSet<String>,
241 recursion_stack: &mut HashSet<String>,
242 path: &mut Vec<String>,
243 ) -> Option<Vec<String>> {
244 visited.insert(handler.to_string());
245 recursion_stack.insert(handler.to_string());
246 path.push(handler.to_string());
247
248 if let Some(deps) = self.dependencies.get(handler) {
249 for dep in deps {
250 if !visited.contains(dep) {
251 if let Some(cycle) = self.dfs_detect_cycle(dep, visited, recursion_stack, path)
252 {
253 return Some(cycle);
254 }
255 } else if recursion_stack.contains(dep) {
256 if let Some(cycle_start) = path.iter().position(|h| h == dep) {
258 let mut cycle = path[cycle_start..].to_vec();
259 cycle.push(dep.to_string());
260 return Some(cycle);
261 }
262 }
263 }
264 }
265
266 path.pop();
267 recursion_stack.remove(handler);
268 None
269 }
270}
271
272impl Default for HandlerCallGraph {
273 fn default() -> Self {
274 Self::new()
275 }
276}