oxihuman_core/
signal_handler.rs1#![allow(dead_code)]
4
5use std::collections::HashMap;
8
9#[allow(dead_code)]
11#[derive(Debug, Clone)]
12pub struct HandlerEntry {
13 pub name: String,
14 pub signal: String,
15 pub priority: i32,
16 pub enabled: bool,
17 pub call_count: u64,
18}
19
20#[allow(dead_code)]
22pub struct SignalHandler {
23 handlers: HashMap<String, HandlerEntry>,
24 dispatch_log: Vec<(String, u64)>,
25 total_dispatched: u64,
26}
27
28#[allow(dead_code)]
29impl SignalHandler {
30 pub fn new() -> Self {
31 Self {
32 handlers: HashMap::new(),
33 dispatch_log: Vec::new(),
34 total_dispatched: 0,
35 }
36 }
37
38 pub fn register(&mut self, name: &str, signal: &str, priority: i32) {
40 self.handlers.insert(
41 name.to_string(),
42 HandlerEntry {
43 name: name.to_string(),
44 signal: signal.to_string(),
45 priority,
46 enabled: true,
47 call_count: 0,
48 },
49 );
50 }
51
52 pub fn unregister(&mut self, name: &str) -> bool {
54 self.handlers.remove(name).is_some()
55 }
56
57 pub fn set_enabled(&mut self, name: &str, enabled: bool) -> bool {
59 if let Some(h) = self.handlers.get_mut(name) {
60 h.enabled = enabled;
61 true
62 } else {
63 false
64 }
65 }
66
67 pub fn dispatch(&mut self, signal: &str, timestamp: u64) -> usize {
69 self.total_dispatched += 1;
70 self.dispatch_log.push((signal.to_string(), timestamp));
71 let mut count = 0;
72 let names: Vec<String> = self.handlers.keys().cloned().collect();
73 let mut sorted: Vec<(i32, String)> = names
74 .iter()
75 .filter_map(|n| {
76 let h = &self.handlers[n];
77 if h.signal == signal && h.enabled {
78 Some((h.priority, n.clone()))
79 } else {
80 None
81 }
82 })
83 .collect();
84 sorted.sort_by(|a, b| b.0.cmp(&a.0));
85 for (_, name) in sorted {
86 if let Some(h) = self.handlers.get_mut(&name) {
87 h.call_count += 1;
88 count += 1;
89 }
90 }
91 count
92 }
93
94 pub fn get(&self, name: &str) -> Option<&HandlerEntry> {
95 self.handlers.get(name)
96 }
97
98 pub fn handler_count(&self) -> usize {
99 self.handlers.len()
100 }
101
102 pub fn total_dispatched(&self) -> u64 {
103 self.total_dispatched
104 }
105
106 pub fn dispatch_log_len(&self) -> usize {
107 self.dispatch_log.len()
108 }
109
110 pub fn clear_log(&mut self) {
111 self.dispatch_log.clear();
112 }
113
114 pub fn clear_all(&mut self) {
115 self.handlers.clear();
116 self.dispatch_log.clear();
117 self.total_dispatched = 0;
118 }
119
120 pub fn is_empty(&self) -> bool {
121 self.handlers.is_empty()
122 }
123}
124
125impl Default for SignalHandler {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
131pub fn new_signal_handler() -> SignalHandler {
132 SignalHandler::new()
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn register_and_dispatch() {
141 let mut sh = new_signal_handler();
142 sh.register("h1", "resize", 0);
143 let count = sh.dispatch("resize", 100);
144 assert_eq!(count, 1);
145 }
146
147 #[test]
148 fn unregister_removes() {
149 let mut sh = new_signal_handler();
150 sh.register("h1", "exit", 0);
151 assert!(sh.unregister("h1"));
152 assert_eq!(sh.dispatch("exit", 0), 0);
153 }
154
155 #[test]
156 fn disabled_handler_not_called() {
157 let mut sh = new_signal_handler();
158 sh.register("h1", "pause", 5);
159 sh.set_enabled("h1", false);
160 assert_eq!(sh.dispatch("pause", 1), 0);
161 }
162
163 #[test]
164 fn re_enable_handler() {
165 let mut sh = new_signal_handler();
166 sh.register("h1", "resume", 1);
167 sh.set_enabled("h1", false);
168 sh.set_enabled("h1", true);
169 assert_eq!(sh.dispatch("resume", 1), 1);
170 }
171
172 #[test]
173 fn call_count_increments() {
174 let mut sh = new_signal_handler();
175 sh.register("h1", "tick", 0);
176 sh.dispatch("tick", 1);
177 sh.dispatch("tick", 2);
178 assert_eq!(sh.get("h1").expect("should succeed").call_count, 2);
179 }
180
181 #[test]
182 fn total_dispatched_increments() {
183 let mut sh = new_signal_handler();
184 sh.dispatch("x", 0);
185 sh.dispatch("x", 1);
186 assert_eq!(sh.total_dispatched(), 2);
187 }
188
189 #[test]
190 fn handler_count() {
191 let mut sh = new_signal_handler();
192 sh.register("a", "s", 0);
193 sh.register("b", "s", 0);
194 assert_eq!(sh.handler_count(), 2);
195 }
196
197 #[test]
198 fn wrong_signal_not_dispatched() {
199 let mut sh = new_signal_handler();
200 sh.register("h1", "usr1", 0);
201 assert_eq!(sh.dispatch("usr2", 0), 0);
202 }
203
204 #[test]
205 fn clear_all() {
206 let mut sh = new_signal_handler();
207 sh.register("h1", "s", 0);
208 sh.dispatch("s", 0);
209 sh.clear_all();
210 assert!(sh.is_empty());
211 assert_eq!(sh.total_dispatched(), 0);
212 }
213
214 #[test]
215 fn clear_log() {
216 let mut sh = new_signal_handler();
217 sh.dispatch("s", 1);
218 assert_eq!(sh.dispatch_log_len(), 1);
219 sh.clear_log();
220 assert_eq!(sh.dispatch_log_len(), 0);
221 }
222}