Skip to main content

oxihuman_core/
dispatch_table.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5use std::collections::HashMap;
6
7/// A table that maps string keys to handler IDs for dispatch.
8#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct DispatchTable {
11    handlers: HashMap<String, HandlerEntry>,
12    next_id: u64,
13}
14
15#[allow(dead_code)]
16#[derive(Debug, Clone)]
17pub struct HandlerEntry {
18    pub id: u64,
19    pub name: String,
20    pub priority: i32,
21    pub enabled: bool,
22}
23
24impl Default for DispatchTable {
25    fn default() -> Self {
26        Self::new()
27    }
28}
29
30#[allow(dead_code)]
31impl DispatchTable {
32    pub fn new() -> Self {
33        Self {
34            handlers: HashMap::new(),
35            next_id: 1,
36        }
37    }
38
39    pub fn register(&mut self, key: &str, priority: i32) -> u64 {
40        let id = self.next_id;
41        self.next_id += 1;
42        self.handlers.insert(
43            key.to_string(),
44            HandlerEntry {
45                id,
46                name: key.to_string(),
47                priority,
48                enabled: true,
49            },
50        );
51        id
52    }
53
54    pub fn unregister(&mut self, key: &str) -> bool {
55        self.handlers.remove(key).is_some()
56    }
57
58    pub fn lookup(&self, key: &str) -> Option<u64> {
59        self.handlers.get(key).filter(|h| h.enabled).map(|h| h.id)
60    }
61
62    pub fn contains(&self, key: &str) -> bool {
63        self.handlers.contains_key(key)
64    }
65
66    pub fn set_enabled(&mut self, key: &str, enabled: bool) -> bool {
67        if let Some(h) = self.handlers.get_mut(key) {
68            h.enabled = enabled;
69            true
70        } else {
71            false
72        }
73    }
74
75    pub fn is_enabled(&self, key: &str) -> bool {
76        self.handlers.get(key).is_some_and(|h| h.enabled)
77    }
78
79    pub fn count(&self) -> usize {
80        self.handlers.len()
81    }
82
83    pub fn enabled_count(&self) -> usize {
84        self.handlers.values().filter(|h| h.enabled).count()
85    }
86
87    pub fn keys(&self) -> Vec<&str> {
88        self.handlers.keys().map(|k| k.as_str()).collect()
89    }
90
91    pub fn by_priority(&self) -> Vec<&HandlerEntry> {
92        let mut entries: Vec<&HandlerEntry> = self.handlers.values().collect();
93        entries.sort_by(|a, b| b.priority.cmp(&a.priority));
94        entries
95    }
96
97    pub fn clear(&mut self) {
98        self.handlers.clear();
99    }
100
101    pub fn get_entry(&self, key: &str) -> Option<&HandlerEntry> {
102        self.handlers.get(key)
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[test]
111    fn test_new() {
112        let dt = DispatchTable::new();
113        assert_eq!(dt.count(), 0);
114    }
115
116    #[test]
117    fn test_register_and_lookup() {
118        let mut dt = DispatchTable::new();
119        let id = dt.register("click", 0);
120        assert_eq!(dt.lookup("click"), Some(id));
121    }
122
123    #[test]
124    fn test_unregister() {
125        let mut dt = DispatchTable::new();
126        dt.register("click", 0);
127        assert!(dt.unregister("click"));
128        assert!(!dt.contains("click"));
129    }
130
131    #[test]
132    fn test_disable() {
133        let mut dt = DispatchTable::new();
134        dt.register("click", 0);
135        dt.set_enabled("click", false);
136        assert!(dt.lookup("click").is_none());
137        assert!(!dt.is_enabled("click"));
138    }
139
140    #[test]
141    fn test_contains() {
142        let mut dt = DispatchTable::new();
143        dt.register("a", 0);
144        assert!(dt.contains("a"));
145        assert!(!dt.contains("b"));
146    }
147
148    #[test]
149    fn test_by_priority() {
150        let mut dt = DispatchTable::new();
151        dt.register("low", 1);
152        dt.register("high", 10);
153        dt.register("mid", 5);
154        let sorted = dt.by_priority();
155        assert_eq!(sorted[0].name, "high");
156    }
157
158    #[test]
159    fn test_enabled_count() {
160        let mut dt = DispatchTable::new();
161        dt.register("a", 0);
162        dt.register("b", 0);
163        dt.set_enabled("b", false);
164        assert_eq!(dt.enabled_count(), 1);
165    }
166
167    #[test]
168    fn test_clear() {
169        let mut dt = DispatchTable::new();
170        dt.register("a", 0);
171        dt.clear();
172        assert_eq!(dt.count(), 0);
173    }
174
175    #[test]
176    fn test_unique_ids() {
177        let mut dt = DispatchTable::new();
178        let id1 = dt.register("a", 0);
179        let id2 = dt.register("b", 0);
180        assert_ne!(id1, id2);
181    }
182
183    #[test]
184    fn test_get_entry() {
185        let mut dt = DispatchTable::new();
186        dt.register("x", 42);
187        let entry = dt.get_entry("x").expect("should succeed");
188        assert_eq!(entry.priority, 42);
189    }
190}