Skip to main content

oxihuman_core/
double_map.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 bidirectional map between two string key spaces.
8#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct DoubleMap {
11    forward: HashMap<String, String>,
12    backward: HashMap<String, String>,
13}
14
15impl Default for DoubleMap {
16    fn default() -> Self {
17        Self::new()
18    }
19}
20
21#[allow(dead_code)]
22impl DoubleMap {
23    pub fn new() -> Self {
24        Self {
25            forward: HashMap::new(),
26            backward: HashMap::new(),
27        }
28    }
29
30    pub fn insert(&mut self, key: &str, value: &str) -> bool {
31        if self.forward.contains_key(key) || self.backward.contains_key(value) {
32            return false;
33        }
34        self.forward.insert(key.to_string(), value.to_string());
35        self.backward.insert(value.to_string(), key.to_string());
36        true
37    }
38
39    pub fn get_forward(&self, key: &str) -> Option<&str> {
40        self.forward.get(key).map(|v| v.as_str())
41    }
42
43    pub fn get_backward(&self, value: &str) -> Option<&str> {
44        self.backward.get(value).map(|v| v.as_str())
45    }
46
47    pub fn remove_by_key(&mut self, key: &str) -> bool {
48        if let Some(value) = self.forward.remove(key) {
49            self.backward.remove(&value);
50            true
51        } else {
52            false
53        }
54    }
55
56    pub fn remove_by_value(&mut self, value: &str) -> bool {
57        if let Some(key) = self.backward.remove(value) {
58            self.forward.remove(&key);
59            true
60        } else {
61            false
62        }
63    }
64
65    pub fn contains_key(&self, key: &str) -> bool {
66        self.forward.contains_key(key)
67    }
68
69    pub fn contains_value(&self, value: &str) -> bool {
70        self.backward.contains_key(value)
71    }
72
73    pub fn count(&self) -> usize {
74        self.forward.len()
75    }
76
77    pub fn is_empty(&self) -> bool {
78        self.forward.is_empty()
79    }
80
81    pub fn keys(&self) -> Vec<&str> {
82        self.forward.keys().map(|k| k.as_str()).collect()
83    }
84
85    pub fn values(&self) -> Vec<&str> {
86        self.backward.keys().map(|k| k.as_str()).collect()
87    }
88
89    pub fn clear(&mut self) {
90        self.forward.clear();
91        self.backward.clear();
92    }
93
94    pub fn to_pairs(&self) -> Vec<(&str, &str)> {
95        self.forward
96            .iter()
97            .map(|(k, v)| (k.as_str(), v.as_str()))
98            .collect()
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105
106    #[test]
107    fn test_new() {
108        let dm = DoubleMap::new();
109        assert!(dm.is_empty());
110    }
111
112    #[test]
113    fn test_insert_and_get() {
114        let mut dm = DoubleMap::new();
115        assert!(dm.insert("a", "1"));
116        assert_eq!(dm.get_forward("a"), Some("1"));
117        assert_eq!(dm.get_backward("1"), Some("a"));
118    }
119
120    #[test]
121    fn test_duplicate_key() {
122        let mut dm = DoubleMap::new();
123        dm.insert("a", "1");
124        assert!(!dm.insert("a", "2"));
125    }
126
127    #[test]
128    fn test_duplicate_value() {
129        let mut dm = DoubleMap::new();
130        dm.insert("a", "1");
131        assert!(!dm.insert("b", "1"));
132    }
133
134    #[test]
135    fn test_remove_by_key() {
136        let mut dm = DoubleMap::new();
137        dm.insert("a", "1");
138        assert!(dm.remove_by_key("a"));
139        assert!(!dm.contains_key("a"));
140        assert!(!dm.contains_value("1"));
141    }
142
143    #[test]
144    fn test_remove_by_value() {
145        let mut dm = DoubleMap::new();
146        dm.insert("a", "1");
147        assert!(dm.remove_by_value("1"));
148        assert!(dm.is_empty());
149    }
150
151    #[test]
152    fn test_contains() {
153        let mut dm = DoubleMap::new();
154        dm.insert("x", "y");
155        assert!(dm.contains_key("x"));
156        assert!(dm.contains_value("y"));
157        assert!(!dm.contains_key("y"));
158    }
159
160    #[test]
161    fn test_count() {
162        let mut dm = DoubleMap::new();
163        dm.insert("a", "1");
164        dm.insert("b", "2");
165        assert_eq!(dm.count(), 2);
166    }
167
168    #[test]
169    fn test_clear() {
170        let mut dm = DoubleMap::new();
171        dm.insert("a", "1");
172        dm.clear();
173        assert!(dm.is_empty());
174    }
175
176    #[test]
177    fn test_to_pairs() {
178        let mut dm = DoubleMap::new();
179        dm.insert("a", "1");
180        let pairs = dm.to_pairs();
181        assert_eq!(pairs.len(), 1);
182        assert_eq!(pairs[0], ("a", "1"));
183    }
184}