Skip to main content

acktor_ipc/
double_map.rs

1//! A map-like container supporting lookup by two independent key types.
2//!
3//! [`DoubleMap`] keeps two internal [`HashMap`]s: one owns the value (keyed by `K1`)
4//! and the other is an index from `K2` to `K1`. Lookups by either key type are
5//! `O(1)`, and insertions, removals, and clears keep the two maps in sync.
6//!
7//! The public API mirrors [`std::collections::HashMap`] as closely as possible, with
8//! key-centric methods (`get`, `contains`, `remove`, …) split into `_by_key1` and
9//! `_by_key2` variants.
10//!
11// completely generated by Claude Code
12
13use std::borrow::Borrow;
14use std::collections::hash_map;
15use std::fmt::{self, Debug, Formatter};
16use std::hash::Hash;
17use std::ops::Index;
18
19use ahash::{HashMap, HashMapExt};
20
21pub use std::collections::TryReserveError;
22
23mod errors;
24pub use errors::KeyConflictError;
25
26mod entry;
27pub use entry::{Entry, OccupiedEntry, VacantEntry};
28
29mod iter;
30pub use iter::{Drain, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values, ValuesMut};
31
32/// A map-like container supporting `O(1)` lookup by two key types.
33pub struct DoubleMap<K1, K2, V> {
34    /// Owns the value. Each entry also carries the `K2` key so removals and
35    /// iteration can expose it without extra bookkeeping.
36    primary: HashMap<K1, (K2, V)>,
37    /// Index from the `K2` key back to the `K1` key.
38    secondary: HashMap<K2, K1>,
39}
40
41impl<K1, K2, V> DoubleMap<K1, K2, V> {
42    /// Constructs a new, empty [`DoubleMap`].
43    pub fn new() -> Self {
44        Self {
45            primary: HashMap::default(),
46            secondary: HashMap::default(),
47        }
48    }
49
50    /// Constructs a new, empty [`DoubleMap`] with at least the specified capacity for
51    /// both internal maps.
52    pub fn with_capacity(capacity: usize) -> Self {
53        Self {
54            primary: HashMap::with_capacity(capacity),
55            secondary: HashMap::with_capacity(capacity),
56        }
57    }
58
59    /// Returns the minimum of the two internal capacities.
60    pub fn capacity(&self) -> usize {
61        self.primary.capacity().min(self.secondary.capacity())
62    }
63
64    /// Returns an iterator over the keys, yielding a `(&K1, &K2)` tuple for each entry.
65    pub fn keys(&self) -> Keys<'_, K1, K2, V> {
66        Keys::new(self.primary.iter())
67    }
68
69    /// Creates a consuming iterator yielding owned `(K1, K2)` key tuples in arbitrary
70    /// order. The map cannot be used after calling this.
71    pub fn into_keys(self) -> IntoKeys<K1, K2, V> {
72        let Self {
73            primary,
74            secondary: _,
75        } = self;
76        IntoKeys::new(primary.into_iter())
77    }
78
79    /// Returns an iterator over the values.
80    pub fn values(&self) -> Values<'_, K1, K2, V> {
81        Values::new(self.primary.values())
82    }
83
84    /// Returns an iterator yielding mutable references to each value.
85    pub fn values_mut(&mut self) -> ValuesMut<'_, K1, K2, V> {
86        ValuesMut::new(self.primary.values_mut())
87    }
88
89    /// Creates a consuming iterator yielding owned values in arbitrary order. The map
90    /// cannot be used after calling this.
91    pub fn into_values(self) -> IntoValues<K1, K2, V> {
92        let Self {
93            primary,
94            secondary: _,
95        } = self;
96        IntoValues::new(primary.into_values())
97    }
98
99    /// Returns an iterator yielding every entry as `(&K1, &K2, &V)`.
100    pub fn iter(&self) -> Iter<'_, K1, K2, V> {
101        Iter::new(self.primary.iter())
102    }
103
104    /// Returns an iterator yielding every entry as `(&K1, &K2, &mut V)`.
105    ///
106    /// Neither key is mutably accessible — mutating them would desync the two
107    /// internal maps.
108    pub fn iter_mut(&mut self) -> IterMut<'_, K1, K2, V> {
109        IterMut::new(self.primary.iter_mut())
110    }
111
112    /// Returns the number of entries in the map.
113    pub fn len(&self) -> usize {
114        self.primary.len()
115    }
116
117    /// Returns `true` if the map contains no entries.
118    pub fn is_empty(&self) -> bool {
119        self.primary.is_empty()
120    }
121
122    /// Clears the map, returning all entries as an iterator.
123    pub fn drain(&mut self) -> Drain<'_, K1, K2, V> {
124        self.secondary.clear();
125        Drain::new(self.primary.drain())
126    }
127
128    /// Removes all entries.
129    pub fn clear(&mut self) {
130        self.primary.clear();
131        self.secondary.clear();
132    }
133}
134
135impl<K1, K2, V> DoubleMap<K1, K2, V>
136where
137    K1: Eq + Hash,
138    K2: Eq + Hash,
139{
140    /// Retains only the entries for which the `predicate` returns `true`.
141    pub fn retain<F>(&mut self, mut f: F)
142    where
143        F: FnMut(&K1, &K2, &mut V) -> bool,
144    {
145        self.primary.retain(|k1, (k2, v)| {
146            let keep = f(k1, k2, v);
147            if !keep {
148                self.secondary.remove(k2);
149            }
150            keep
151        });
152    }
153
154    /// Reserves capacity for at least `additional` more entries in both internal maps.
155    pub fn reserve(&mut self, additional: usize) {
156        self.primary.reserve(additional);
157        self.secondary.reserve(additional);
158    }
159
160    /// Tries to reserve capacity for at least `additional` more entries in both
161    /// internal maps. Returns an error on allocation failure.
162    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
163        self.primary.try_reserve(additional)?;
164        self.secondary.try_reserve(additional)?;
165        Ok(())
166    }
167
168    /// Shrinks the internal maps to fit the current number of entries.
169    pub fn shrink_to_fit(&mut self) {
170        self.primary.shrink_to_fit();
171        self.secondary.shrink_to_fit();
172    }
173
174    /// Shrinks the internal maps toward the given lower bound.
175    pub fn shrink_to(&mut self, min_capacity: usize) {
176        self.primary.shrink_to(min_capacity);
177        self.secondary.shrink_to(min_capacity);
178    }
179
180    /// Returns a reference to the value corresponding to the `K1` key.
181    pub fn get_by_key1<Q>(&self, key: &Q) -> Option<&V>
182    where
183        K1: Borrow<Q>,
184        Q: Eq + Hash + ?Sized,
185    {
186        self.primary.get(key).map(|(_, v)| v)
187    }
188
189    /// Returns a reference to the value corresponding to the `K2` key.
190    pub fn get_by_key2<Q>(&self, key: &Q) -> Option<&V>
191    where
192        K2: Borrow<Q>,
193        Q: Eq + Hash + ?Sized,
194    {
195        let k1 = self.secondary.get(key)?;
196        self.primary.get(k1).map(|(_, v)| v)
197    }
198
199    /// Returns a reference to the value for the entry whose `K1` key equals `key1`
200    /// **and** whose `K2` key equals `key2`. Returns `None` if either key is missing,
201    /// or if they refer to different entries.
202    pub fn get_by_keys<Q1, Q2>(&self, key1: &Q1, key2: &Q2) -> Option<&V>
203    where
204        K1: Borrow<Q1>,
205        K2: Borrow<Q2>,
206        Q1: Eq + Hash + ?Sized,
207        Q2: Eq + Hash + ?Sized,
208    {
209        let (k2_stored, v) = self.primary.get(key1)?;
210        if k2_stored.borrow() == key2 {
211            Some(v)
212        } else {
213            None
214        }
215    }
216
217    /// Returns the stored `K1` key and value for the entry identified by the given
218    /// `K1` key.
219    pub fn get_key1_value<Q>(&self, key: &Q) -> Option<(&K1, &V)>
220    where
221        K1: Borrow<Q>,
222        Q: Eq + Hash + ?Sized,
223    {
224        self.primary.get_key_value(key).map(|(k1, (_, v))| (k1, v))
225    }
226
227    /// Returns the stored `K2` key and value for the entry identified by the given
228    /// `K2` key.
229    pub fn get_key2_value<Q>(&self, key: &Q) -> Option<(&K2, &V)>
230    where
231        K2: Borrow<Q>,
232        Q: Eq + Hash + ?Sized,
233    {
234        let (k2_stored, k1) = self.secondary.get_key_value(key)?;
235        let (_, v) = self.primary.get(k1)?;
236        Some((k2_stored, v))
237    }
238
239    /// Returns the stored `(K1, K2, V)` triple for the entry whose `K1` key equals
240    /// `key1` **and** whose `K2` key equals `key2`. Returns `None` if either key is
241    /// missing, or if they refer to different entries.
242    pub fn get_keys_value<Q1, Q2>(&self, key1: &Q1, key2: &Q2) -> Option<(&K1, &K2, &V)>
243    where
244        K1: Borrow<Q1>,
245        K2: Borrow<Q2>,
246        Q1: Eq + Hash + ?Sized,
247        Q2: Eq + Hash + ?Sized,
248    {
249        let (k1_stored, (k2_stored, v)) = self.primary.get_key_value(key1)?;
250        if k2_stored.borrow() == key2 {
251            Some((k1_stored, k2_stored, v))
252        } else {
253            None
254        }
255    }
256
257    /// Returns `true` if the map contains a value for the given `K1` key.
258    pub fn contains_key1<Q>(&self, key: &Q) -> bool
259    where
260        K1: Borrow<Q>,
261        Q: Eq + Hash + ?Sized,
262    {
263        self.primary.contains_key(key)
264    }
265
266    /// Returns `true` if the map contains a value for the given `K2` key.
267    pub fn contains_key2<Q>(&self, key: &Q) -> bool
268    where
269        K2: Borrow<Q>,
270        Q: Eq + Hash + ?Sized,
271    {
272        self.secondary.contains_key(key)
273    }
274
275    /// Returns `true` if the map contains an entry whose `K1` key equals `key1`
276    /// **and** whose `K2` key equals `key2` (i.e. both keys refer to the same entry).
277    pub fn contains_keys<Q1, Q2>(&self, key1: &Q1, key2: &Q2) -> bool
278    where
279        K1: Borrow<Q1>,
280        K2: Borrow<Q2>,
281        Q1: Eq + Hash + ?Sized,
282        Q2: Eq + Hash + ?Sized,
283    {
284        self.get_by_keys(key1, key2).is_some()
285    }
286
287    /// Returns a mutable reference to the value corresponding to the `K1` key.
288    pub fn get_mut_by_key1<Q>(&mut self, key: &Q) -> Option<&mut V>
289    where
290        K1: Borrow<Q>,
291        Q: Eq + Hash + ?Sized,
292    {
293        self.primary.get_mut(key).map(|(_, v)| v)
294    }
295
296    /// Returns a mutable reference to the value corresponding to the `K2` key.
297    pub fn get_mut_by_key2<Q>(&mut self, key: &Q) -> Option<&mut V>
298    where
299        K2: Borrow<Q>,
300        Q: Eq + Hash + ?Sized,
301    {
302        let k1 = self.secondary.get(key)?;
303        self.primary.get_mut(k1).map(|(_, v)| v)
304    }
305
306    /// Returns a mutable reference to the value for the entry whose `K1` key equals
307    /// `key1` **and** whose `K2` key equals `key2`. Returns `None` if either key is
308    /// missing, or if they refer to different entries.
309    pub fn get_mut_by_keys<Q1, Q2>(&mut self, key1: &Q1, key2: &Q2) -> Option<&mut V>
310    where
311        K1: Borrow<Q1>,
312        K2: Borrow<Q2>,
313        Q1: Eq + Hash + ?Sized,
314        Q2: Eq + Hash + ?Sized,
315    {
316        let (k2_stored, v) = self.primary.get_mut(key1)?;
317        if <K2 as Borrow<Q2>>::borrow(k2_stored) == key2 {
318            Some(v)
319        } else {
320            None
321        }
322    }
323
324    /// Removes an entry by its `K1` key, returning the value if it was present.
325    pub fn remove_by_key1<Q>(&mut self, key: &Q) -> Option<V>
326    where
327        K1: Borrow<Q>,
328        Q: Eq + Hash + ?Sized,
329    {
330        let (k2, value) = self.primary.remove(key)?;
331        self.secondary.remove(&k2);
332        Some(value)
333    }
334
335    /// Removes an entry by its `K2` key, returning the value if it was present.
336    pub fn remove_by_key2<Q>(&mut self, key: &Q) -> Option<V>
337    where
338        K2: Borrow<Q>,
339        Q: Eq + Hash + ?Sized,
340    {
341        let k1 = self.secondary.remove(key)?;
342        let (_, value) = self
343            .primary
344            .remove(&k1)
345            .expect("primary map must contain key 1 whenever secondary map points to it");
346        Some(value)
347    }
348
349    /// Removes an entry only if its `K1` key equals `key1` **and** its `K2` key equals
350    /// `key2`. Returns the value on success, or `None` if either key is missing or they
351    /// refer to different entries. On mismatch, the map is unchanged.
352    pub fn remove_by_keys<Q1, Q2>(&mut self, key1: &Q1, key2: &Q2) -> Option<V>
353    where
354        K1: Borrow<Q1>,
355        K2: Borrow<Q2>,
356        Q1: Eq + Hash + ?Sized,
357        Q2: Eq + Hash + ?Sized,
358    {
359        let (k1, (k2, value)) = self.primary.remove_entry(key1)?;
360        if <K2 as Borrow<Q2>>::borrow(&k2) != key2 {
361            self.primary.insert(k1, (k2, value));
362            return None;
363        }
364        self.secondary.remove::<K2>(&k2);
365        Some(value)
366    }
367
368    /// Removes an entry by its `K1` key, returning the full `(K1, K2, V)` triple if it
369    /// was present.
370    pub fn remove_entry_by_key1<Q>(&mut self, key: &Q) -> Option<(K1, K2, V)>
371    where
372        K1: Borrow<Q>,
373        Q: Eq + Hash + ?Sized,
374    {
375        let (k1, (k2, value)) = self.primary.remove_entry(key)?;
376        self.secondary.remove(&k2);
377        Some((k1, k2, value))
378    }
379
380    /// Removes an entry by its `K2` key, returning the full `(K1, K2, V)` triple if it
381    /// was present.
382    pub fn remove_entry_by_key2<Q>(&mut self, key: &Q) -> Option<(K1, K2, V)>
383    where
384        K2: Borrow<Q>,
385        Q: Eq + Hash + ?Sized,
386    {
387        let k1 = self.secondary.remove(key)?;
388        let (k1, (k2, value)) = self
389            .primary
390            .remove_entry(&k1)
391            .expect("primary map must contain key 1 whenever secondary map points to it");
392        Some((k1, k2, value))
393    }
394
395    /// Removes an entry only if its `K1` key equals `key1` **and** its `K2` key equals
396    /// `key2`. Returns the full `(K1, K2, V)` triple on success, or `None` if either
397    /// key is missing or they refer to different entries. On mismatch, the map is
398    /// unchanged.
399    pub fn remove_entry_by_keys<Q1, Q2>(&mut self, key1: &Q1, key2: &Q2) -> Option<(K1, K2, V)>
400    where
401        K1: Borrow<Q1>,
402        K2: Borrow<Q2>,
403        Q1: Eq + Hash + ?Sized,
404        Q2: Eq + Hash + ?Sized,
405    {
406        let (k1, (k2, value)) = self.primary.remove_entry(key1)?;
407        if <K2 as Borrow<Q2>>::borrow(&k2) != key2 {
408            self.primary.insert(k1, (k2, value));
409            return None;
410        }
411        self.secondary.remove::<K2>(&k2);
412        Some((k1, k2, value))
413    }
414}
415
416impl<K1, K2, V> DoubleMap<K1, K2, V>
417where
418    K1: Eq + Hash + Clone,
419    K2: Eq + Hash + Clone,
420{
421    /// Gets the given `(key1, key2)` pair's [`Entry`] in the map for in-place
422    /// manipulation.
423    ///
424    /// - Returns `Ok(Entry::Occupied)` if both keys refer to the same existing entry.
425    /// - Returns `Ok(Entry::Vacant)` if neither key is present.
426    /// - Returns [`Err(KeyConflictError)`][KeyConflictError] if the two keys clash
427    ///   with existing entries. In the error case the map is unchanged and the
428    ///   rejected `(K1, K2)` pair is returned.
429    pub fn entry(
430        &mut self,
431        key1: K1,
432        key2: K2,
433    ) -> Result<Entry<'_, K1, K2, V>, KeyConflictError<K1, K2>> {
434        let key1_matches_key2 = self
435            .primary
436            .get(&key1)
437            .map(|(k2_stored, _)| k2_stored == &key2);
438        let key2_present = self.secondary.contains_key(&key2);
439
440        match (key1_matches_key2, key2_present) {
441            // both keys identify the same existing entry
442            (Some(true), _) => {
443                let hash_map::Entry::Occupied(e1) = self.primary.entry(key1) else {
444                    unreachable!("primary.get just observed key 1 as present");
445                };
446                let hash_map::Entry::Occupied(e2) = self.secondary.entry(key2) else {
447                    unreachable!(
448                        "key 1's stored key 2 matches the argument, so secondary must contain it",
449                    );
450                };
451                Ok(Entry::Occupied(OccupiedEntry::new(e1, e2)))
452            }
453            // neither key is present
454            (None, false) => {
455                let hash_map::Entry::Vacant(e1) = self.primary.entry(key1) else {
456                    unreachable!("primary.get just observed key 1 as absent");
457                };
458                let hash_map::Entry::Vacant(e2) = self.secondary.entry(key2) else {
459                    unreachable!("secondary.contains_key just observed key 2 as absent");
460                };
461                Ok(Entry::Vacant(VacantEntry::new(e1, e2)))
462            }
463            // `key1` is present but paired with a different `key2`
464            (Some(false), true) => Err(KeyConflictError::BothKeysExist(key1, key2, ())),
465            (Some(false), false) => Err(KeyConflictError::Key1Exists(key1, key2, ())),
466            // `key1` is absent but `key2` is present (paired with a different `key1`)
467            (None, true) => Err(KeyConflictError::Key2Exists(key1, key2, ())),
468        }
469    }
470
471    /// Inserts a new entry, or updates the value if both keys are already present and
472    /// refer to the same entry.
473    ///
474    /// - Returns `Ok(None)` when neither key was present and a fresh entry was inserted.
475    /// - Returns `Ok(Some(old_value))` when both keys matched the same existing entry
476    ///   and its value was replaced.
477    /// - Returns [`Err(KeyConflictError)`][KeyConflictError] if the two keys clash
478    ///   with existing entries. In all error cases the map is unchanged and the rejected
479    ///   triple is returned.
480    pub fn insert(
481        &mut self,
482        key1: K1,
483        key2: K2,
484        value: V,
485    ) -> Result<Option<V>, KeyConflictError<K1, K2, V>> {
486        if let Some((existing_k2, _)) = self.primary.get(&key1) {
487            if existing_k2 == &key2 {
488                // both keys refer to the same entry; update the value in place
489                let old = self.primary.insert(key1, (key2, value));
490                return Ok(old.map(|(_, v_old)| v_old));
491            }
492            // `key1` is in the map paired with a different `key2`. Distinguish
493            // "only key1 clashes" from "both keys are present in different entries"
494            if self.secondary.contains_key(&key2) {
495                return Err(KeyConflictError::BothKeysExist(key1, key2, value));
496            }
497            return Err(KeyConflictError::Key1Exists(key1, key2, value));
498        }
499
500        // `key1` is not present; ensure `key2` is also absent
501        if self.secondary.contains_key(&key2) {
502            return Err(KeyConflictError::Key2Exists(key1, key2, value));
503        }
504
505        self.secondary.insert(key2.clone(), key1.clone());
506        self.primary.insert(key1, (key2, value));
507
508        Ok(None)
509    }
510}
511
512impl<K1, K2, V> Clone for DoubleMap<K1, K2, V>
513where
514    K1: Clone,
515    K2: Clone,
516    V: Clone,
517{
518    fn clone(&self) -> Self {
519        Self {
520            primary: self.primary.clone(),
521            secondary: self.secondary.clone(),
522        }
523    }
524
525    fn clone_from(&mut self, source: &Self) {
526        self.primary.clone_from(&source.primary);
527        self.secondary.clone_from(&source.secondary);
528    }
529}
530
531impl<K1, K2, V> PartialEq for DoubleMap<K1, K2, V>
532where
533    K1: Eq + Hash,
534    K2: Eq + Hash,
535    V: PartialEq,
536{
537    fn eq(&self, other: &Self) -> bool {
538        self.primary == other.primary
539    }
540}
541
542impl<K1, K2, V> Eq for DoubleMap<K1, K2, V>
543where
544    K1: Eq + Hash,
545    K2: Eq + Hash,
546    V: Eq,
547{
548}
549
550impl<K1, K2, V> Debug for DoubleMap<K1, K2, V>
551where
552    K1: Debug,
553    K2: Debug,
554    V: Debug,
555{
556    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
557        f.debug_map()
558            .entries(self.iter().map(|(k1, k2, v)| ((k1, k2), v)))
559            .finish()
560    }
561}
562
563impl<K1, K2, V> Default for DoubleMap<K1, K2, V> {
564    fn default() -> Self {
565        Self::new()
566    }
567}
568
569impl<K1, K2, V, Q> Index<&Q> for DoubleMap<K1, K2, V>
570where
571    K1: Eq + Hash + Borrow<Q>,
572    K2: Eq + Hash,
573    Q: Eq + Hash + ?Sized,
574{
575    type Output = V;
576
577    /// Returns a reference to the value corresponding to the supplied key1.
578    ///
579    /// # Panics
580    ///
581    /// Panics if the key is not present in the map.
582    fn index(&self, key: &Q) -> &V {
583        self.get_by_key1(key).expect("no entry found for key")
584    }
585}
586
587impl<K1, K2, V> IntoIterator for DoubleMap<K1, K2, V> {
588    type Item = (K1, K2, V);
589    type IntoIter = IntoIter<K1, K2, V>;
590
591    /// Consumes the map, yielding owned `(K1, K2, V)` triples.
592    fn into_iter(self) -> Self::IntoIter {
593        let Self {
594            primary,
595            secondary: _,
596        } = self;
597        IntoIter::new(primary.into_iter())
598    }
599}
600
601impl<'a, K1, K2, V> IntoIterator for &'a DoubleMap<K1, K2, V> {
602    type Item = (&'a K1, &'a K2, &'a V);
603    type IntoIter = Iter<'a, K1, K2, V>;
604
605    /// Borrows the map, yielding `(&K1, &K2, &V)` triples.
606    fn into_iter(self) -> Self::IntoIter {
607        self.iter()
608    }
609}
610
611impl<'a, K1, K2, V> IntoIterator for &'a mut DoubleMap<K1, K2, V> {
612    type Item = (&'a K1, &'a K2, &'a mut V);
613    type IntoIter = IterMut<'a, K1, K2, V>;
614
615    /// Mutably borrows the map, yielding `(&K1, &K2, &mut V)` triples. Keys are exposed
616    /// immutably to preserve the invariant that both internal maps stay in sync.
617    fn into_iter(self) -> Self::IntoIter {
618        self.iter_mut()
619    }
620}
621
622impl<K1, K2, V> Extend<(K1, K2, V)> for DoubleMap<K1, K2, V>
623where
624    K1: Eq + Hash + Clone,
625    K2: Eq + Hash + Clone,
626{
627    /// Extends the map with `(K1, K2, V)` triples from any iterator.
628    ///
629    /// Triples whose keys conflict with an existing entry (same `K1` mapped to a
630    /// different `K2`, or same `K2` mapped to a different `K1`) are silently skipped
631    /// and the map is left unchanged for that triple. A consistent repeat (same `K1`
632    /// **and** same `K2`) updates the value.
633    fn extend<I>(&mut self, iter: I)
634    where
635        I: IntoIterator<Item = (K1, K2, V)>,
636    {
637        let iter = iter.into_iter();
638        let (lower, _) = iter.size_hint();
639        self.reserve(lower);
640        for (k1, k2, v) in iter {
641            let _ = self.insert(k1, k2, v);
642        }
643    }
644}
645
646impl<'a, K1, K2, V> Extend<(&'a K1, &'a K2, &'a V)> for DoubleMap<K1, K2, V>
647where
648    K1: Eq + Hash + Copy,
649    K2: Eq + Hash + Copy,
650    V: Copy,
651{
652    /// Extends the map with borrowed `(&K1, &K2, &V)` triples, copying each element into
653    /// place.
654    ///
655    /// Conflicting triples are silently skipped, same as the owned-triple [`Extend`] impl.
656    fn extend<I>(&mut self, iter: I)
657    where
658        I: IntoIterator<Item = (&'a K1, &'a K2, &'a V)>,
659    {
660        self.extend(iter.into_iter().map(|(k1, k2, v)| (*k1, *k2, *v)));
661    }
662}
663
664impl<K1, K2, V> FromIterator<(K1, K2, V)> for DoubleMap<K1, K2, V>
665where
666    K1: Eq + Hash + Clone,
667    K2: Eq + Hash + Clone,
668{
669    /// Collects `(K1, K2, V)` triples into a fresh [`DoubleMap`].
670    ///
671    /// Conflicting triples are silently skipped, same as [`Extend`].
672    fn from_iter<I>(iter: I) -> Self
673    where
674        I: IntoIterator<Item = (K1, K2, V)>,
675    {
676        let mut map = Self::new();
677        map.extend(iter);
678        map
679    }
680}
681
682impl<K1, K2, V, const N: usize> From<[(K1, K2, V); N]> for DoubleMap<K1, K2, V>
683where
684    K1: Eq + Hash + Clone,
685    K2: Eq + Hash + Clone,
686{
687    /// Builds a [`DoubleMap`] from an array of `(K1, K2, V)` triples.
688    ///
689    /// Conflicting triples are silently skipped, same as [`FromIterator`].
690    fn from(arr: [(K1, K2, V); N]) -> Self {
691        Self::from_iter(arr)
692    }
693}
694
695#[cfg(test)]
696mod tests {
697    use super::*;
698
699    fn fresh() -> DoubleMap<u64, String, i32> {
700        DoubleMap::new()
701    }
702
703    fn populated() -> DoubleMap<u64, String, i32> {
704        let mut map = fresh();
705        map.insert(1, "foo".to_string(), 10).unwrap();
706        map.insert(2, "bar".to_string(), 20).unwrap();
707        map
708    }
709
710    mod construction {
711        use pretty_assertions::assert_eq;
712
713        use super::*;
714
715        #[test]
716        fn new() {
717            let map = fresh();
718            assert!(map.is_empty());
719            assert_eq!(map.len(), 0);
720        }
721
722        #[test]
723        fn with_capacity() {
724            let map: DoubleMap<u64, String, i32> = DoubleMap::with_capacity(64);
725            assert!(map.capacity() >= 64);
726            assert!(map.is_empty());
727        }
728    }
729
730    mod capacity {
731        use pretty_assertions::assert_eq;
732
733        use super::*;
734
735        #[test]
736        fn reserve() -> anyhow::Result<()> {
737            let mut map = fresh();
738            map.reserve(128);
739            assert!(map.capacity() >= 128);
740            map.insert(1, "foo".to_string(), 10)?;
741            assert_eq!(map.get_by_key1(&1), Some(&10));
742
743            Ok(())
744        }
745
746        #[test]
747        fn try_reserve() -> anyhow::Result<()> {
748            let mut map: DoubleMap<u64, String, i32> = fresh();
749            map.try_reserve(64)?;
750            assert!(map.capacity() >= 64);
751
752            Ok(())
753        }
754
755        #[test]
756        fn shrink_to_fit() {
757            let mut map = populated();
758            map.reserve(128);
759            map.shrink_to_fit();
760            assert_eq!(map.get_by_key1(&1), Some(&10));
761            assert_eq!(map.get_by_key2("bar"), Some(&20));
762        }
763
764        #[test]
765        fn shrink_to() {
766            let mut map = populated();
767            map.reserve(256);
768            map.shrink_to(32);
769            assert!(map.capacity() >= 32);
770            assert_eq!(map.get_by_key1(&1), Some(&10));
771            assert_eq!(map.get_by_key2("bar"), Some(&20));
772        }
773    }
774
775    mod insert {
776        use pretty_assertions::assert_eq;
777
778        use super::*;
779
780        #[test]
781        fn insert() -> anyhow::Result<()> {
782            let mut map = fresh();
783
784            // New entry.
785            assert_eq!(map.insert(1, "foo".to_string(), 10)?, None);
786            assert_eq!(map.get_by_key1(&1), Some(&10));
787            assert_eq!(map.get_by_key2("foo"), Some(&10));
788
789            // Same (key1, key2) pair replaces the value.
790            assert_eq!(map.insert(1, "foo".to_string(), 99)?, Some(10));
791            assert_eq!(map.get_by_key1(&1), Some(&99));
792
793            // key1 collides with a different key2.
794            let err = map.insert(1, "bar".to_string(), 20).unwrap_err();
795            assert!(matches!(err, KeyConflictError::Key1Exists(1, _, 20)));
796
797            // key2 collides with a different key1.
798            let err = map.insert(2, "foo".to_string(), 30).unwrap_err();
799            assert!(matches!(err, KeyConflictError::Key2Exists(2, _, 30)));
800
801            // Both keys present in different entries.
802            map.insert(2, "bar".to_string(), 20)?;
803            let err = map.insert(1, "bar".to_string(), 42).unwrap_err();
804            assert!(matches!(err, KeyConflictError::BothKeysExist(1, _, 42)));
805
806            Ok(())
807        }
808    }
809
810    mod get {
811        use pretty_assertions::assert_eq;
812
813        use super::*;
814
815        #[test]
816        fn by_key1() {
817            let map = populated();
818            assert_eq!(map.get_by_key1(&1), Some(&10));
819            assert_eq!(map.get_by_key1(&99), None);
820        }
821
822        #[test]
823        fn by_key2() {
824            let map = populated();
825            // `&str` for a `String` key exercises the `Borrow<Q>` path.
826            assert_eq!(map.get_by_key2("foo"), Some(&10));
827            assert_eq!(map.get_by_key2("missing"), None);
828        }
829
830        #[test]
831        fn by_keys() {
832            let map = populated();
833            assert_eq!(map.get_by_keys(&1, "foo"), Some(&10));
834            // Mismatch.
835            assert_eq!(map.get_by_keys(&1, "bar"), None);
836            // Missing.
837            assert_eq!(map.get_by_keys(&99, "foo"), None);
838        }
839
840        #[test]
841        fn key1_value() {
842            let map = populated();
843            let (k1, v) = map.get_key1_value(&1).unwrap();
844            assert_eq!((*k1, *v), (1, 10));
845            assert!(map.get_key1_value(&99).is_none());
846        }
847
848        #[test]
849        fn key2_value() {
850            let map = populated();
851            let (k2, v) = map.get_key2_value("foo").unwrap();
852            assert_eq!((k2.as_str(), *v), ("foo", 10));
853            assert!(map.get_key2_value("missing").is_none());
854        }
855
856        #[test]
857        fn keys_value() {
858            let map = populated();
859            let (k1, k2, v) = map.get_keys_value(&1, "foo").unwrap();
860            assert_eq!((*k1, k2.as_str(), *v), (1, "foo", 10));
861            assert!(map.get_keys_value(&1, "bar").is_none());
862        }
863
864        #[test]
865        fn contains_key1() {
866            let map = populated();
867            assert!(map.contains_key1(&1));
868            assert!(!map.contains_key1(&99));
869        }
870
871        #[test]
872        fn contains_key2() {
873            let map = populated();
874            assert!(map.contains_key2("foo"));
875            assert!(!map.contains_key2("missing"));
876        }
877
878        #[test]
879        fn contains_keys() {
880            let map = populated();
881            assert!(map.contains_keys(&1, "foo"));
882            assert!(!map.contains_keys(&1, "bar"));
883            assert!(!map.contains_keys(&99, "foo"));
884        }
885    }
886
887    mod modify {
888        use pretty_assertions::assert_eq;
889
890        use super::*;
891
892        #[test]
893        fn get_mut_by_key1() {
894            let mut map = populated();
895            *map.get_mut_by_key1(&1).unwrap() = 42;
896            assert_eq!(map.get_by_key1(&1), Some(&42));
897            assert_eq!(map.get_by_key2("foo"), Some(&42));
898        }
899
900        #[test]
901        fn get_mut_by_key2() {
902            let mut map = populated();
903            *map.get_mut_by_key2("foo").unwrap() = 42;
904            assert_eq!(map.get_by_key1(&1), Some(&42));
905        }
906
907        #[test]
908        fn get_mut_by_keys() {
909            let mut map = populated();
910            *map.get_mut_by_keys(&1, "foo").unwrap() = 42;
911            assert_eq!(map.get_by_key1(&1), Some(&42));
912            // Mismatch: no mutation.
913            assert!(map.get_mut_by_keys(&1, "bar").is_none());
914        }
915
916        #[test]
917        fn clear() {
918            let mut map = populated();
919            map.clear();
920            assert!(map.is_empty());
921            assert!(map.get_by_key1(&1).is_none());
922        }
923
924        #[test]
925        fn drain() {
926            let mut map = populated();
927            let mut drained: Vec<_> = map.drain().collect();
928            drained.sort_by_key(|(k1, _, _)| *k1);
929            assert_eq!(
930                drained,
931                vec![(1, "foo".to_string(), 10), (2, "bar".to_string(), 20)]
932            );
933            assert!(map.is_empty());
934        }
935
936        #[test]
937        fn retain() {
938            let mut map = populated();
939            map.retain(|_, _, v| *v >= 20);
940            assert_eq!(map.len(), 1);
941            assert!(!map.contains_key1(&1));
942            assert!(!map.contains_key2("foo"));
943            assert!(map.contains_key1(&2));
944        }
945    }
946
947    mod remove {
948        use pretty_assertions::assert_eq;
949
950        use super::*;
951
952        #[test]
953        fn by_key1() {
954            let mut map = populated();
955            assert_eq!(map.remove_by_key1(&1), Some(10));
956            assert!(!map.contains_key1(&1));
957            assert!(!map.contains_key2("foo"));
958            assert_eq!(map.remove_by_key1(&99), None);
959        }
960
961        #[test]
962        fn by_key2() {
963            let mut map = populated();
964            assert_eq!(map.remove_by_key2("foo"), Some(10));
965            assert!(!map.contains_key1(&1));
966            assert!(!map.contains_key2("foo"));
967            assert_eq!(map.remove_by_key2("missing"), None);
968        }
969
970        #[test]
971        fn by_keys() {
972            let mut map = populated();
973
974            // Mismatch: no removal, map unchanged.
975            assert_eq!(map.remove_by_keys(&1, "bar"), None);
976            assert_eq!(map.len(), 2);
977            assert!(map.contains_key1(&1));
978
979            // Match: both indexes cleaned.
980            assert_eq!(map.remove_by_keys(&1, "foo"), Some(10));
981            assert!(!map.contains_key1(&1));
982            assert!(!map.contains_key2("foo"));
983        }
984
985        #[test]
986        fn entry_by_key1() {
987            let mut map = populated();
988            assert_eq!(
989                map.remove_entry_by_key1(&1),
990                Some((1, "foo".to_string(), 10))
991            );
992            assert!(map.remove_entry_by_key1(&99).is_none());
993        }
994
995        #[test]
996        fn entry_by_key2() {
997            let mut map = populated();
998            assert_eq!(
999                map.remove_entry_by_key2("foo"),
1000                Some((1, "foo".to_string(), 10))
1001            );
1002            assert!(map.remove_entry_by_key2("missing").is_none());
1003        }
1004
1005        #[test]
1006        fn entry_by_keys() {
1007            let mut map = populated();
1008            assert_eq!(
1009                map.remove_entry_by_keys(&1, "foo"),
1010                Some((1, "foo".to_string(), 10))
1011            );
1012            // Mismatch: no removal.
1013            assert!(map.remove_entry_by_keys(&2, "foo").is_none());
1014        }
1015    }
1016
1017    mod iter {
1018        use pretty_assertions::assert_eq;
1019
1020        use super::*;
1021
1022        #[test]
1023        fn iter() {
1024            let map = populated();
1025            let mut entries: Vec<_> = map
1026                .iter()
1027                .map(|(k1, k2, v)| (*k1, k2.clone(), *v))
1028                .collect();
1029            entries.sort_by_key(|(k1, _, _)| *k1);
1030            assert_eq!(
1031                entries,
1032                vec![(1, "foo".to_string(), 10), (2, "bar".to_string(), 20)]
1033            );
1034        }
1035
1036        #[test]
1037        fn iter_mut() {
1038            let mut map = populated();
1039            // Uses `IntoIterator for &mut DoubleMap`, which delegates to `iter_mut`.
1040            for (_, _, v) in &mut map {
1041                *v *= 10;
1042            }
1043            assert_eq!(map.get_by_key1(&1), Some(&100));
1044            assert_eq!(map.get_by_key1(&2), Some(&200));
1045        }
1046
1047        #[test]
1048        fn for_shared_ref() {
1049            let map = populated();
1050            let mut count = 0;
1051            for (_, _, _) in &map {
1052                count += 1;
1053            }
1054            assert_eq!(count, 2);
1055        }
1056
1057        #[test]
1058        fn keys() {
1059            let map = populated();
1060            let mut keys: Vec<_> = map.keys().map(|(k1, k2)| (*k1, k2.clone())).collect();
1061            keys.sort_by_key(|(k1, _)| *k1);
1062            assert_eq!(keys, vec![(1, "foo".to_string()), (2, "bar".to_string())]);
1063        }
1064
1065        #[test]
1066        fn values() {
1067            let map = populated();
1068            let mut values: Vec<_> = map.values().copied().collect();
1069            values.sort();
1070            assert_eq!(values, vec![10, 20]);
1071        }
1072
1073        #[test]
1074        fn values_mut() {
1075            let mut map = populated();
1076            for v in map.values_mut() {
1077                *v += 1;
1078            }
1079            assert_eq!(map.get_by_key1(&1), Some(&11));
1080        }
1081
1082        #[test]
1083        fn into_iter() {
1084            let mut collected: Vec<_> = populated().into_iter().collect();
1085            collected.sort_by_key(|(k1, _, _)| *k1);
1086            assert_eq!(
1087                collected,
1088                vec![(1, "foo".to_string(), 10), (2, "bar".to_string(), 20)]
1089            );
1090        }
1091
1092        #[test]
1093        fn into_keys() {
1094            let mut keys: Vec<_> = populated().into_keys().collect();
1095            keys.sort_by_key(|(k1, _)| *k1);
1096            assert_eq!(keys, vec![(1, "foo".to_string()), (2, "bar".to_string())]);
1097        }
1098
1099        #[test]
1100        fn into_values() {
1101            let mut values: Vec<_> = populated().into_values().collect();
1102            values.sort();
1103            assert_eq!(values, vec![10, 20]);
1104        }
1105
1106        #[test]
1107        fn iter_clone_and_size_hint() {
1108            let map = populated();
1109            let it = map.iter();
1110            assert_eq!(it.len(), 2);
1111            assert_eq!(it.size_hint(), (2, Some(2)));
1112
1113            let it2 = it.clone();
1114            let mut a: Vec<_> = it.map(|(k1, _, _)| *k1).collect();
1115            let mut b: Vec<_> = it2.map(|(k1, _, _)| *k1).collect();
1116            a.sort();
1117            b.sort();
1118            assert_eq!(a, b);
1119            assert_eq!(a, vec![1, 2]);
1120        }
1121
1122        #[test]
1123        fn keys_values_clone() {
1124            let map = populated();
1125
1126            let keys = map.keys();
1127            let keys2 = keys.clone();
1128            assert_eq!(keys.len(), 2);
1129            let mut a: Vec<_> = keys.map(|(k1, _)| *k1).collect();
1130            let mut b: Vec<_> = keys2.map(|(k1, _)| *k1).collect();
1131            a.sort();
1132            b.sort();
1133            assert_eq!(a, b);
1134
1135            let values = map.values();
1136            let values2 = values.clone();
1137            assert_eq!(values.len(), 2);
1138            let mut a: Vec<_> = values.copied().collect();
1139            let mut b: Vec<_> = values2.copied().collect();
1140            a.sort();
1141            b.sort();
1142            assert_eq!(a, b);
1143        }
1144
1145        #[test]
1146        fn size_hints() {
1147            let mut map = populated();
1148            assert_eq!(map.iter_mut().len(), 2);
1149            assert_eq!(map.iter_mut().size_hint(), (2, Some(2)));
1150            assert_eq!(map.values_mut().len(), 2);
1151            assert_eq!(map.values_mut().size_hint(), (2, Some(2)));
1152
1153            // Drain consumes the map; use a fresh clone.
1154            let mut drain_src = map.clone();
1155            let drain = drain_src.drain();
1156            assert_eq!(drain.len(), 2);
1157            assert_eq!(drain.size_hint(), (2, Some(2)));
1158
1159            assert_eq!(map.clone().into_iter().len(), 2);
1160            assert_eq!(map.clone().into_keys().len(), 2);
1161            assert_eq!(map.into_values().len(), 2);
1162        }
1163    }
1164
1165    mod entry {
1166        use pretty_assertions::assert_eq;
1167
1168        use super::*;
1169
1170        #[test]
1171        fn entry() -> anyhow::Result<()> {
1172            let mut map = populated();
1173
1174            // Occupied: both keys identify the same entry.
1175            match map.entry(1, "foo".to_string())? {
1176                Entry::Occupied(mut occ) => {
1177                    assert_eq!(*occ.get(), 10);
1178                    *occ.get_mut() = 42;
1179                    let old = occ.insert(7);
1180                    assert_eq!(old, 42);
1181                    assert_eq!(occ.remove_entry(), (1, "foo".to_string(), 7));
1182                }
1183                Entry::Vacant(_) => panic!("expected Occupied"),
1184            }
1185            assert!(!map.contains_key1(&1));
1186
1187            // Vacant: neither key is present.
1188            match map.entry(3, "baz".to_string())? {
1189                Entry::Vacant(vac) => {
1190                    assert_eq!(*vac.key1(), 3);
1191                    assert_eq!(vac.key2(), "baz");
1192                    vac.insert(30);
1193                }
1194                Entry::Occupied(_) => panic!("expected Vacant"),
1195            }
1196            assert_eq!(map.get_by_key1(&3), Some(&30));
1197
1198            // Err: key1 clashes with a different key2.
1199            assert!(matches!(
1200                map.entry(2, "quux".to_string()),
1201                Err(KeyConflictError::Key1Exists(2, _, _))
1202            ));
1203
1204            // Err: key2 clashes with a different key1.
1205            assert!(matches!(
1206                map.entry(99, "bar".to_string()),
1207                Err(KeyConflictError::Key2Exists(99, _, _))
1208            ));
1209
1210            // Err: both keys present in different entries.
1211            assert!(matches!(
1212                map.entry(2, "baz".to_string()),
1213                Err(KeyConflictError::BothKeysExist(2, _, _))
1214            ));
1215
1216            Ok(())
1217        }
1218
1219        #[test]
1220        fn key_accessors() -> anyhow::Result<()> {
1221            let mut map = populated();
1222
1223            // Occupied branch.
1224            let e = map.entry(1, "foo".to_string())?;
1225            assert_eq!(*e.key1(), 1);
1226            assert_eq!(e.key2(), "foo");
1227            let (k1, k2) = e.keys();
1228            assert_eq!((*k1, k2.as_str()), (1, "foo"));
1229
1230            // Vacant branch.
1231            let e = map.entry(3, "baz".to_string())?;
1232            assert_eq!(*e.key1(), 3);
1233            assert_eq!(e.key2(), "baz");
1234            let (k1, k2) = e.keys();
1235            assert_eq!((*k1, k2.as_str()), (3, "baz"));
1236
1237            Ok(())
1238        }
1239
1240        #[test]
1241        fn or_insert() -> anyhow::Result<()> {
1242            let mut map = fresh();
1243
1244            // Vacant: inserts and returns a mutable reference.
1245            let v = map.entry(1, "foo".to_string())?.or_insert(10);
1246            *v = 42;
1247            assert_eq!(map.get_by_key1(&1), Some(&42));
1248
1249            // Occupied: returns existing value, does not overwrite.
1250            let v = map.entry(1, "foo".to_string())?.or_insert(99);
1251            assert_eq!(*v, 42);
1252
1253            Ok(())
1254        }
1255
1256        #[test]
1257        fn or_insert_with() -> anyhow::Result<()> {
1258            let mut map = populated();
1259
1260            // Occupied: closure must not run.
1261            let v = map
1262                .entry(1, "foo".to_string())?
1263                .or_insert_with(|| panic!("closure should not run on Occupied"));
1264            assert_eq!(*v, 10);
1265
1266            // Vacant: closure runs, value is inserted.
1267            let v = map.entry(3, "baz".to_string())?.or_insert_with(|| 30);
1268            assert_eq!(*v, 30);
1269            assert_eq!(map.get_by_key1(&3), Some(&30));
1270
1271            Ok(())
1272        }
1273
1274        #[test]
1275        fn or_insert_with_keys() -> anyhow::Result<()> {
1276            let mut map = populated();
1277
1278            // Occupied: closure must not run.
1279            let v = map
1280                .entry(1, "foo".to_string())?
1281                .or_insert_with_keys(|_, _| panic!("closure should not run on Occupied"));
1282            assert_eq!(*v, 10);
1283
1284            // Vacant: closure sees the keys.
1285            let v = map
1286                .entry(3, "baz".to_string())?
1287                .or_insert_with_keys(|k1, k2| *k1 as i32 + k2.len() as i32);
1288            assert_eq!(*v, 3 + 3);
1289
1290            Ok(())
1291        }
1292
1293        #[test]
1294        fn or_default() -> anyhow::Result<()> {
1295            let mut map: DoubleMap<u64, String, i32> = fresh();
1296            let v = map.entry(1, "foo".to_string())?.or_default();
1297            assert_eq!(*v, 0);
1298
1299            Ok(())
1300        }
1301
1302        #[test]
1303        fn and_modify() -> anyhow::Result<()> {
1304            let mut map = populated();
1305
1306            // Occupied: closure runs.
1307            map.entry(1, "foo".to_string())?
1308                .and_modify(|v| *v *= 2)
1309                .or_insert(0);
1310            assert_eq!(map.get_by_key1(&1), Some(&20));
1311
1312            // Vacant: closure is a no-op, or_insert inserts.
1313            map.entry(3, "baz".to_string())?
1314                .and_modify(|v| *v *= 2)
1315                .or_insert(5);
1316            assert_eq!(map.get_by_key1(&3), Some(&5));
1317
1318            Ok(())
1319        }
1320
1321        #[test]
1322        fn insert_entry() -> anyhow::Result<()> {
1323            let mut map = populated();
1324
1325            // Occupied: overwrites in place.
1326            let occ = map.entry(1, "foo".to_string())?.insert_entry(42);
1327            assert_eq!(*occ.get(), 42);
1328            assert_eq!(map.get_by_key1(&1), Some(&42));
1329
1330            // Vacant: inserts fresh entry.
1331            let occ = map.entry(3, "baz".to_string())?.insert_entry(30);
1332            assert_eq!(*occ.get(), 30);
1333            assert_eq!(map.get_by_key1(&3), Some(&30));
1334            assert_eq!(map.get_by_key2("baz"), Some(&30));
1335
1336            Ok(())
1337        }
1338
1339        #[test]
1340        fn vacant_into_keys() -> anyhow::Result<()> {
1341            let mut map = fresh();
1342            let (k1, k2) = match map.entry(1u64, "foo".to_string())? {
1343                Entry::Vacant(v) => v.into_keys(),
1344                Entry::Occupied(_) => panic!("expected Vacant"),
1345            };
1346            assert_eq!((k1, k2.as_str()), (1, "foo"));
1347            // into_keys does not insert — map is still empty.
1348            assert!(map.is_empty());
1349
1350            Ok(())
1351        }
1352
1353        #[test]
1354        fn vacant_insert_entry() -> anyhow::Result<()> {
1355            let mut map = fresh();
1356            match map.entry(1u64, "foo".to_string())? {
1357                Entry::Vacant(v) => {
1358                    let occ = v.insert_entry(10);
1359                    assert_eq!(*occ.get(), 10);
1360                }
1361                Entry::Occupied(_) => panic!("expected Vacant"),
1362            }
1363            assert_eq!(map.get_by_key1(&1), Some(&10));
1364            assert_eq!(map.get_by_key2("foo"), Some(&10));
1365
1366            Ok(())
1367        }
1368
1369        #[test]
1370        fn occupied_accessors() -> anyhow::Result<()> {
1371            let mut map = populated();
1372            match map.entry(1u64, "foo".to_string())? {
1373                Entry::Occupied(occ) => {
1374                    assert_eq!(*occ.key1(), 1);
1375                    assert_eq!(occ.key2(), "foo");
1376                    let (k1, k2) = occ.keys();
1377                    assert_eq!((*k1, k2.as_str()), (1, "foo"));
1378                }
1379                Entry::Vacant(_) => panic!("expected Occupied"),
1380            }
1381
1382            Ok(())
1383        }
1384
1385        #[test]
1386        fn occupied_remove() -> anyhow::Result<()> {
1387            let mut map = populated();
1388            match map.entry(1u64, "foo".to_string())? {
1389                Entry::Occupied(occ) => assert_eq!(occ.remove(), 10),
1390                Entry::Vacant(_) => panic!("expected Occupied"),
1391            }
1392            assert!(!map.contains_key1(&1));
1393            assert!(!map.contains_key2("foo"));
1394            assert_eq!(map.len(), 1);
1395
1396            Ok(())
1397        }
1398    }
1399
1400    mod traits {
1401        use pretty_assertions::{assert_eq, assert_ne};
1402
1403        use super::*;
1404
1405        #[test]
1406        fn from() {
1407            // Conflicting triples are silently skipped.
1408            let map: DoubleMap<u64, String, i32> = DoubleMap::from([
1409                (1, "foo".to_string(), 10),
1410                (2, "bar".to_string(), 20),
1411                (1, "zzz".to_string(), 99),
1412            ]);
1413            assert_eq!(map.len(), 2);
1414            assert_eq!(map.get_by_key1(&1), Some(&10));
1415            assert!(!map.contains_key2("zzz"));
1416        }
1417
1418        #[test]
1419        fn from_iter() {
1420            let map: DoubleMap<u64, String, i32> =
1421                vec![(1u64, "foo".to_string(), 10), (2u64, "bar".to_string(), 20)]
1422                    .into_iter()
1423                    .collect();
1424            assert_eq!(map.len(), 2);
1425            assert_eq!(map.get_by_key1(&1), Some(&10));
1426        }
1427
1428        #[test]
1429        fn extend() -> anyhow::Result<()> {
1430            let mut map = fresh();
1431            map.insert(1, "foo".to_string(), 10)?;
1432
1433            // Conflicting triples are silently skipped; consistent repeats update the value.
1434            map.extend(vec![
1435                (2, "bar".to_string(), 20),
1436                (1, "zzz".to_string(), 99),
1437                (1, "foo".to_string(), 42),
1438            ]);
1439            assert_eq!(map.len(), 2);
1440            assert_eq!(map.get_by_key1(&1), Some(&42));
1441            assert_eq!(map.get_by_key1(&2), Some(&20));
1442            assert!(!map.contains_key2("zzz"));
1443
1444            Ok(())
1445        }
1446
1447        #[test]
1448        fn extend_borrowed() {
1449            let mut map: DoubleMap<u64, u64, i32> = DoubleMap::new();
1450            let items = [(1u64, 10u64, 100i32), (2, 20, 200)];
1451            map.extend(items.iter().map(|(k1, k2, v)| (k1, k2, v)));
1452            assert_eq!(map.len(), 2);
1453            assert_eq!(map.get_by_key1(&1), Some(&100));
1454            assert_eq!(map.get_by_key2(&20), Some(&200));
1455        }
1456
1457        #[test]
1458        fn index() {
1459            let map = populated();
1460            assert_eq!(map[&1], 10);
1461            assert_eq!(map[&2], 20);
1462        }
1463
1464        #[test]
1465        #[should_panic(expected = "no entry found for key")]
1466        fn index_panics() {
1467            let _ = fresh()[&1];
1468        }
1469
1470        #[test]
1471        fn clone() {
1472            let cloned = populated().clone();
1473            assert_eq!(cloned.len(), 2);
1474            assert_eq!(cloned.get_by_key1(&1), Some(&10));
1475            assert_eq!(cloned.get_by_key2("bar"), Some(&20));
1476        }
1477
1478        #[test]
1479        fn clone_from() -> anyhow::Result<()> {
1480            let mut target = fresh();
1481            target.insert(99, "old".to_string(), 999)?;
1482            target.clone_from(&populated());
1483            assert_eq!(target.len(), 2);
1484            assert_eq!(target.get_by_key1(&1), Some(&10));
1485            assert!(!target.contains_key1(&99));
1486            assert!(!target.contains_key2("old"));
1487
1488            Ok(())
1489        }
1490
1491        #[test]
1492        fn eq() -> anyhow::Result<()> {
1493            let a = populated();
1494
1495            // Insertion order does not matter.
1496            let mut b = fresh();
1497            b.insert(2, "bar".to_string(), 20)?;
1498            b.insert(1, "foo".to_string(), 10)?;
1499            assert_eq!(a, b);
1500
1501            // Differing value.
1502            let mut c = fresh();
1503            c.insert(1, "foo".to_string(), 10)?;
1504            c.insert(2, "bar".to_string(), 99)?;
1505            assert_ne!(a, c);
1506
1507            Ok(())
1508        }
1509
1510        #[test]
1511        fn debug_fmt() -> anyhow::Result<()> {
1512            let mut map = fresh();
1513            map.insert(1, "foo".to_string(), 10)?;
1514            let s = format!("{:?}", map);
1515            assert!(s.contains('1'));
1516            assert!(s.contains("foo"));
1517            assert!(s.contains("10"));
1518
1519            Ok(())
1520        }
1521    }
1522
1523    mod errors {
1524        use super::*;
1525
1526        #[test]
1527        fn key_conflict_display() {
1528            let e1: KeyConflictError<u64, String> = KeyConflictError::Key1Exists(1, "a".into(), ());
1529            let e2: KeyConflictError<u64, String> = KeyConflictError::Key2Exists(1, "a".into(), ());
1530            let e3: KeyConflictError<u64, String> =
1531                KeyConflictError::BothKeysExist(1, "a".into(), ());
1532            assert!(e1.to_string().contains("key 1"));
1533            assert!(e2.to_string().contains("key 2"));
1534            assert!(e3.to_string().contains("both"));
1535        }
1536    }
1537}