Skip to main content

oxihuman_core/
selector_map.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! A map that tracks one selected/active key among its entries.
6
7use std::collections::HashMap;
8
9/// A map with a notion of an "active" or selected entry.
10#[allow(dead_code)]
11pub struct SelectorMap<V> {
12    entries: HashMap<String, V>,
13    selected: Option<String>,
14    change_count: u64,
15}
16
17#[allow(dead_code)]
18impl<V: Clone> SelectorMap<V> {
19    pub fn new() -> Self {
20        Self {
21            entries: HashMap::new(),
22            selected: None,
23            change_count: 0,
24        }
25    }
26
27    pub fn insert(&mut self, key: &str, value: V) {
28        self.entries.insert(key.to_string(), value);
29        self.change_count += 1;
30    }
31
32    pub fn remove(&mut self, key: &str) -> bool {
33        if self.entries.remove(key).is_some() {
34            if self.selected.as_deref() == Some(key) {
35                self.selected = None;
36            }
37            self.change_count += 1;
38            true
39        } else {
40            false
41        }
42    }
43
44    pub fn select(&mut self, key: &str) -> bool {
45        if self.entries.contains_key(key) {
46            self.selected = Some(key.to_string());
47            self.change_count += 1;
48            true
49        } else {
50            false
51        }
52    }
53
54    pub fn deselect(&mut self) {
55        self.selected = None;
56    }
57
58    pub fn selected_key(&self) -> Option<&str> {
59        self.selected.as_deref()
60    }
61
62    pub fn selected_value(&self) -> Option<&V> {
63        self.selected.as_ref().and_then(|k| self.entries.get(k))
64    }
65
66    pub fn get(&self, key: &str) -> Option<&V> {
67        self.entries.get(key)
68    }
69
70    pub fn contains(&self, key: &str) -> bool {
71        self.entries.contains_key(key)
72    }
73
74    pub fn len(&self) -> usize {
75        self.entries.len()
76    }
77
78    pub fn is_empty(&self) -> bool {
79        self.entries.is_empty()
80    }
81
82    pub fn keys(&self) -> Vec<&str> {
83        let mut v: Vec<&str> = self.entries.keys().map(|s| s.as_str()).collect();
84        v.sort_unstable();
85        v
86    }
87
88    pub fn change_count(&self) -> u64 {
89        self.change_count
90    }
91
92    pub fn clear(&mut self) {
93        self.entries.clear();
94        self.selected = None;
95        self.change_count += 1;
96    }
97}
98
99impl<V: Clone> Default for SelectorMap<V> {
100    fn default() -> Self {
101        Self::new()
102    }
103}
104
105pub fn new_selector_map<V: Clone>() -> SelectorMap<V> {
106    SelectorMap::new()
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112
113    #[test]
114    fn insert_and_get() {
115        let mut m: SelectorMap<i32> = new_selector_map();
116        m.insert("a", 1);
117        assert_eq!(m.get("a"), Some(&1));
118    }
119
120    #[test]
121    fn select_returns_value() {
122        let mut m: SelectorMap<i32> = new_selector_map();
123        m.insert("x", 42);
124        assert!(m.select("x"));
125        assert_eq!(m.selected_value(), Some(&42));
126    }
127
128    #[test]
129    fn select_nonexistent_fails() {
130        let mut m: SelectorMap<i32> = new_selector_map();
131        assert!(!m.select("missing"));
132        assert!(m.selected_key().is_none());
133    }
134
135    #[test]
136    fn deselect_clears() {
137        let mut m: SelectorMap<i32> = new_selector_map();
138        m.insert("a", 1);
139        m.select("a");
140        m.deselect();
141        assert!(m.selected_key().is_none());
142    }
143
144    #[test]
145    fn remove_clears_selection() {
146        let mut m: SelectorMap<i32> = new_selector_map();
147        m.insert("a", 5);
148        m.select("a");
149        m.remove("a");
150        assert!(m.selected_key().is_none());
151    }
152
153    #[test]
154    fn len_and_is_empty() {
155        let mut m: SelectorMap<u8> = new_selector_map();
156        assert!(m.is_empty());
157        m.insert("k", 1);
158        assert_eq!(m.len(), 1);
159    }
160
161    #[test]
162    fn change_count_increments() {
163        let mut m: SelectorMap<i32> = new_selector_map();
164        let before = m.change_count();
165        m.insert("a", 1);
166        assert!(m.change_count() > before);
167    }
168
169    #[test]
170    fn clear_removes_all() {
171        let mut m: SelectorMap<i32> = new_selector_map();
172        m.insert("a", 1);
173        m.select("a");
174        m.clear();
175        assert!(m.is_empty());
176        assert!(m.selected_key().is_none());
177    }
178
179    #[test]
180    fn keys_sorted() {
181        let mut m: SelectorMap<i32> = new_selector_map();
182        m.insert("b", 2);
183        m.insert("a", 1);
184        assert_eq!(m.keys(), vec!["a", "b"]);
185    }
186
187    #[test]
188    fn contains_check() {
189        let mut m: SelectorMap<i32> = new_selector_map();
190        m.insert("z", 9);
191        assert!(m.contains("z"));
192        assert!(!m.contains("nope"));
193    }
194}