oxihuman_core/
double_map.rs1#![allow(dead_code)]
4
5use std::collections::HashMap;
6
7#[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}