1use std::borrow::Borrow;
6use std::collections::BTreeMap;
7
8pub struct MultikeyBTreeMap<K1, K2, V> {
13 main: BTreeMap<K1, (K2, V)>,
17 alt: BTreeMap<K2, K1>,
18}
19
20impl<K1, K2, V> Default for MultikeyBTreeMap<K1, K2, V> {
21 fn default() -> Self {
22 Self {
23 main: BTreeMap::new(),
24 alt: BTreeMap::new(),
25 }
26 }
27}
28
29impl<K1, K2, V> MultikeyBTreeMap<K1, K2, V>
30where
31 K1: Clone + Ord,
32 K2: Clone + Ord,
33{
34 pub fn new() -> Self {
36 MultikeyBTreeMap {
37 main: BTreeMap::default(),
38 alt: BTreeMap::default(),
39 }
40 }
41
42 pub fn get<Q>(&self, key: &Q) -> Option<&V>
47 where
48 K1: Borrow<Q>,
49 Q: Ord + ?Sized,
50 {
51 self.main.get(key).map(|(_, v)| v)
52 }
53
54 pub fn get_alt<Q2>(&self, key: &Q2) -> Option<&V>
63 where
64 K2: Borrow<Q2>,
65 Q2: Ord + ?Sized,
66 {
67 if let Some(k) = self.alt.get(key) {
68 self.get(k)
69 } else {
70 None
71 }
72 }
73
74 pub fn insert(&mut self, k1: K1, k2: K2, v: V) -> Option<V> {
82 let oldval = if let Some(oldkey) = self.alt.insert(k2.clone(), k1.clone()) {
83 self.main.remove(&oldkey)
84 } else {
85 None
86 };
87 self.main
88 .insert(k1, (k2.clone(), v))
89 .or(oldval)
90 .map(|(oldk2, v)| {
91 if oldk2 != k2 {
92 self.alt.remove(&oldk2);
93 }
94 v
95 })
96 }
97
98 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
104 where
105 K1: Borrow<Q>,
106 Q: Ord + ?Sized,
107 {
108 self.main.remove(key).map(|(k2, v)| {
109 self.alt.remove(&k2);
110 v
111 })
112 }
113
114 pub fn clear(&mut self) {
116 self.alt.clear();
117 self.main.clear()
118 }
119
120 pub fn apply<F>(&self, f: F)
122 where
123 F: Fn(&V),
124 {
125 self.main.values().for_each(|(_k2, v)| f(v))
126 }
127}
128
129#[cfg(test)]
130mod test {
131 use super::*;
132
133 #[test]
134 fn get() {
135 let mut m = MultikeyBTreeMap::<u64, i64, u32>::new();
136
137 let k1 = 0xc6c8_f5e0_b13e_ed40;
138 let k2 = 0x1a04_ce4b_8329_14fe;
139 let val = 0xf4e3_c360;
140 assert!(m.insert(k1, k2, val).is_none());
141
142 assert_eq!(*m.get(&k1).expect("failed to look up main key"), val);
143 assert_eq!(*m.get_alt(&k2).expect("failed to look up alt key"), val);
144 }
145
146 #[test]
147 fn update_main_key() {
148 let mut m = MultikeyBTreeMap::<u64, i64, u32>::new();
149
150 let k1 = 0xc6c8_f5e0_b13e_ed40;
151 let k2 = 0x1a04_ce4b_8329_14fe;
152 let val = 0xf4e3_c360;
153 assert!(m.insert(k1, k2, val).is_none());
154
155 let new_k1 = 0x3add_f8f8_c7c5_df5e;
156 let val2 = 0x7389_f8a7;
157 assert_eq!(
158 m.insert(new_k1, k2, val2)
159 .expect("failed to update main key"),
160 val
161 );
162
163 assert!(m.get(&k1).is_none());
164 assert_eq!(*m.get(&new_k1).expect("failed to look up main key"), val2);
165 assert_eq!(*m.get_alt(&k2).expect("failed to look up alt key"), val2);
166 }
167
168 #[test]
169 fn update_alt_key() {
170 let mut m = MultikeyBTreeMap::<u64, i64, u32>::new();
171
172 let k1 = 0xc6c8_f5e0_b13e_ed40;
173 let k2 = 0x1a04_ce4b_8329_14fe;
174 let val = 0xf4e3_c360;
175 assert!(m.insert(k1, k2, val).is_none());
176
177 let new_k2 = 0x6825_a60b_61ac_b333;
178 let val2 = 0xbb14_8f2c;
179 assert_eq!(
180 m.insert(k1, new_k2, val2)
181 .expect("failed to update alt key"),
182 val
183 );
184
185 assert!(m.get_alt(&k2).is_none());
186 assert_eq!(*m.get(&k1).expect("failed to look up main key"), val2);
187 assert_eq!(
188 *m.get_alt(&new_k2).expect("failed to look up alt key"),
189 val2
190 );
191 }
192
193 #[test]
194 fn update_value() {
195 let mut m = MultikeyBTreeMap::<u64, i64, u32>::new();
196
197 let k1 = 0xc6c8_f5e0_b13e_ed40;
198 let k2 = 0x1a04_ce4b_8329_14fe;
199 let val = 0xf4e3_c360;
200 assert!(m.insert(k1, k2, val).is_none());
201
202 let val2 = 0xe42d_79ba;
203 assert_eq!(
204 m.insert(k1, k2, val2).expect("failed to update alt key"),
205 val
206 );
207
208 assert_eq!(*m.get(&k1).expect("failed to look up main key"), val2);
209 assert_eq!(*m.get_alt(&k2).expect("failed to look up alt key"), val2);
210 }
211
212 #[test]
213 fn update_both_keys_main() {
214 let mut m = MultikeyBTreeMap::<u64, i64, u32>::new();
215
216 let k1 = 0xc6c8_f5e0_b13e_ed40;
217 let k2 = 0x1a04_ce4b_8329_14fe;
218 let val = 0xf4e3_c360;
219 assert!(m.insert(k1, k2, val).is_none());
220
221 let new_k1 = 0xc980_587a_24b3_ae30;
222 let new_k2 = 0x2773_c5ee_8239_45a2;
223 let val2 = 0x31f4_33f9;
224 assert!(m.insert(new_k1, new_k2, val2).is_none());
225
226 let val3 = 0x8da1_9cf7;
227 assert_eq!(
228 m.insert(k1, new_k2, val3)
229 .expect("failed to update main key"),
230 val
231 );
232
233 assert!(m.get(&new_k1).is_none());
235 assert!(m.get_alt(&k2).is_none());
236
237 assert_eq!(*m.get(&k1).expect("failed to look up main key"), val3);
238 assert_eq!(
239 *m.get_alt(&new_k2).expect("failed to look up alt key"),
240 val3
241 );
242 }
243
244 #[test]
245 fn update_both_keys_alt() {
246 let mut m = MultikeyBTreeMap::<u64, i64, u32>::new();
247
248 let k1 = 0xc6c8_f5e0_b13e_ed40;
249 let k2 = 0x1a04_ce4b_8329_14fe;
250 let val = 0xf4e3_c360;
251 assert!(m.insert(k1, k2, val).is_none());
252
253 let new_k1 = 0xc980_587a_24b3_ae30;
254 let new_k2 = 0x2773_c5ee_8239_45a2;
255 let val2 = 0x31f4_33f9;
256 assert!(m.insert(new_k1, new_k2, val2).is_none());
257
258 let val3 = 0x8da1_9cf7;
259 assert_eq!(
260 m.insert(new_k1, k2, val3)
261 .expect("failed to update main key"),
262 val2
263 );
264
265 assert!(m.get(&k1).is_none());
267 assert!(m.get_alt(&new_k2).is_none());
268
269 assert_eq!(*m.get(&new_k1).expect("failed to look up main key"), val3);
270 assert_eq!(*m.get_alt(&k2).expect("failed to look up alt key"), val3);
271 }
272
273 #[test]
274 fn remove() {
275 let mut m = MultikeyBTreeMap::<u64, i64, u32>::new();
276
277 let k1 = 0xc6c8_f5e0_b13e_ed40;
278 let k2 = 0x1a04_ce4b_8329_14fe;
279 let val = 0xf4e3_c360;
280 assert!(m.insert(k1, k2, val).is_none());
281
282 assert_eq!(m.remove(&k1).expect("failed to remove entry"), val);
283 assert!(m.get(&k1).is_none());
284 assert!(m.get_alt(&k2).is_none());
285 }
286}