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 super::*;
712
713        #[test]
714        fn new() {
715            let map = fresh();
716            assert!(map.is_empty());
717            assert_eq!(map.len(), 0);
718        }
719
720        #[test]
721        fn with_capacity() {
722            let map: DoubleMap<u64, String, i32> = DoubleMap::with_capacity(64);
723            assert!(map.capacity() >= 64);
724            assert!(map.is_empty());
725        }
726    }
727
728    mod capacity {
729        use super::*;
730
731        #[test]
732        fn reserve() {
733            let mut map = fresh();
734            map.reserve(128);
735            assert!(map.capacity() >= 128);
736            map.insert(1, "foo".to_string(), 10).unwrap();
737            assert_eq!(map.get_by_key1(&1), Some(&10));
738        }
739
740        #[test]
741        fn try_reserve() {
742            let mut map: DoubleMap<u64, String, i32> = fresh();
743            map.try_reserve(64).unwrap();
744            assert!(map.capacity() >= 64);
745        }
746
747        #[test]
748        fn shrink_to_fit() {
749            let mut map = populated();
750            map.reserve(128);
751            map.shrink_to_fit();
752            assert_eq!(map.get_by_key1(&1), Some(&10));
753            assert_eq!(map.get_by_key2("bar"), Some(&20));
754        }
755
756        #[test]
757        fn shrink_to() {
758            let mut map = populated();
759            map.reserve(256);
760            map.shrink_to(32);
761            assert!(map.capacity() >= 32);
762            assert_eq!(map.get_by_key1(&1), Some(&10));
763            assert_eq!(map.get_by_key2("bar"), Some(&20));
764        }
765    }
766
767    mod insert {
768        use super::*;
769
770        #[test]
771        fn insert() {
772            let mut map = fresh();
773
774            // New entry.
775            assert_eq!(map.insert(1, "foo".to_string(), 10).unwrap(), None);
776            assert_eq!(map.get_by_key1(&1), Some(&10));
777            assert_eq!(map.get_by_key2("foo"), Some(&10));
778
779            // Same (key1, key2) pair replaces the value.
780            assert_eq!(map.insert(1, "foo".to_string(), 99).unwrap(), Some(10));
781            assert_eq!(map.get_by_key1(&1), Some(&99));
782
783            // key1 collides with a different key2.
784            let err = map.insert(1, "bar".to_string(), 20).unwrap_err();
785            assert!(matches!(err, KeyConflictError::Key1Exists(1, _, 20)));
786
787            // key2 collides with a different key1.
788            let err = map.insert(2, "foo".to_string(), 30).unwrap_err();
789            assert!(matches!(err, KeyConflictError::Key2Exists(2, _, 30)));
790
791            // Both keys present in different entries.
792            map.insert(2, "bar".to_string(), 20).unwrap();
793            let err = map.insert(1, "bar".to_string(), 42).unwrap_err();
794            assert!(matches!(err, KeyConflictError::BothKeysExist(1, _, 42)));
795        }
796    }
797
798    mod get {
799        use super::*;
800
801        #[test]
802        fn by_key1() {
803            let map = populated();
804            assert_eq!(map.get_by_key1(&1), Some(&10));
805            assert_eq!(map.get_by_key1(&99), None);
806        }
807
808        #[test]
809        fn by_key2() {
810            let map = populated();
811            // `&str` for a `String` key exercises the `Borrow<Q>` path.
812            assert_eq!(map.get_by_key2("foo"), Some(&10));
813            assert_eq!(map.get_by_key2("missing"), None);
814        }
815
816        #[test]
817        fn by_keys() {
818            let map = populated();
819            assert_eq!(map.get_by_keys(&1, "foo"), Some(&10));
820            // Mismatch.
821            assert_eq!(map.get_by_keys(&1, "bar"), None);
822            // Missing.
823            assert_eq!(map.get_by_keys(&99, "foo"), None);
824        }
825
826        #[test]
827        fn key1_value() {
828            let map = populated();
829            let (k1, v) = map.get_key1_value(&1).unwrap();
830            assert_eq!((*k1, *v), (1, 10));
831            assert!(map.get_key1_value(&99).is_none());
832        }
833
834        #[test]
835        fn key2_value() {
836            let map = populated();
837            let (k2, v) = map.get_key2_value("foo").unwrap();
838            assert_eq!((k2.as_str(), *v), ("foo", 10));
839            assert!(map.get_key2_value("missing").is_none());
840        }
841
842        #[test]
843        fn keys_value() {
844            let map = populated();
845            let (k1, k2, v) = map.get_keys_value(&1, "foo").unwrap();
846            assert_eq!((*k1, k2.as_str(), *v), (1, "foo", 10));
847            assert!(map.get_keys_value(&1, "bar").is_none());
848        }
849
850        #[test]
851        fn contains_key1() {
852            let map = populated();
853            assert!(map.contains_key1(&1));
854            assert!(!map.contains_key1(&99));
855        }
856
857        #[test]
858        fn contains_key2() {
859            let map = populated();
860            assert!(map.contains_key2("foo"));
861            assert!(!map.contains_key2("missing"));
862        }
863
864        #[test]
865        fn contains_keys() {
866            let map = populated();
867            assert!(map.contains_keys(&1, "foo"));
868            assert!(!map.contains_keys(&1, "bar"));
869            assert!(!map.contains_keys(&99, "foo"));
870        }
871    }
872
873    mod modify {
874        use super::*;
875
876        #[test]
877        fn get_mut_by_key1() {
878            let mut map = populated();
879            *map.get_mut_by_key1(&1).unwrap() = 42;
880            assert_eq!(map.get_by_key1(&1), Some(&42));
881            assert_eq!(map.get_by_key2("foo"), Some(&42));
882        }
883
884        #[test]
885        fn get_mut_by_key2() {
886            let mut map = populated();
887            *map.get_mut_by_key2("foo").unwrap() = 42;
888            assert_eq!(map.get_by_key1(&1), Some(&42));
889        }
890
891        #[test]
892        fn get_mut_by_keys() {
893            let mut map = populated();
894            *map.get_mut_by_keys(&1, "foo").unwrap() = 42;
895            assert_eq!(map.get_by_key1(&1), Some(&42));
896            // Mismatch: no mutation.
897            assert!(map.get_mut_by_keys(&1, "bar").is_none());
898        }
899
900        #[test]
901        fn clear() {
902            let mut map = populated();
903            map.clear();
904            assert!(map.is_empty());
905            assert!(map.get_by_key1(&1).is_none());
906        }
907
908        #[test]
909        fn drain() {
910            let mut map = populated();
911            let mut drained: Vec<_> = map.drain().collect();
912            drained.sort_by_key(|(k1, _, _)| *k1);
913            assert_eq!(
914                drained,
915                vec![(1, "foo".to_string(), 10), (2, "bar".to_string(), 20)]
916            );
917            assert!(map.is_empty());
918        }
919
920        #[test]
921        fn retain() {
922            let mut map = populated();
923            map.retain(|_, _, v| *v >= 20);
924            assert_eq!(map.len(), 1);
925            assert!(!map.contains_key1(&1));
926            assert!(!map.contains_key2("foo"));
927            assert!(map.contains_key1(&2));
928        }
929    }
930
931    mod remove {
932        use super::*;
933
934        #[test]
935        fn by_key1() {
936            let mut map = populated();
937            assert_eq!(map.remove_by_key1(&1), Some(10));
938            assert!(!map.contains_key1(&1));
939            assert!(!map.contains_key2("foo"));
940            assert_eq!(map.remove_by_key1(&99), None);
941        }
942
943        #[test]
944        fn by_key2() {
945            let mut map = populated();
946            assert_eq!(map.remove_by_key2("foo"), Some(10));
947            assert!(!map.contains_key1(&1));
948            assert!(!map.contains_key2("foo"));
949            assert_eq!(map.remove_by_key2("missing"), None);
950        }
951
952        #[test]
953        fn by_keys() {
954            let mut map = populated();
955
956            // Mismatch: no removal, map unchanged.
957            assert_eq!(map.remove_by_keys(&1, "bar"), None);
958            assert_eq!(map.len(), 2);
959            assert!(map.contains_key1(&1));
960
961            // Match: both indexes cleaned.
962            assert_eq!(map.remove_by_keys(&1, "foo"), Some(10));
963            assert!(!map.contains_key1(&1));
964            assert!(!map.contains_key2("foo"));
965        }
966
967        #[test]
968        fn entry_by_key1() {
969            let mut map = populated();
970            assert_eq!(
971                map.remove_entry_by_key1(&1),
972                Some((1, "foo".to_string(), 10))
973            );
974            assert!(map.remove_entry_by_key1(&99).is_none());
975        }
976
977        #[test]
978        fn entry_by_key2() {
979            let mut map = populated();
980            assert_eq!(
981                map.remove_entry_by_key2("foo"),
982                Some((1, "foo".to_string(), 10))
983            );
984            assert!(map.remove_entry_by_key2("missing").is_none());
985        }
986
987        #[test]
988        fn entry_by_keys() {
989            let mut map = populated();
990            assert_eq!(
991                map.remove_entry_by_keys(&1, "foo"),
992                Some((1, "foo".to_string(), 10))
993            );
994            // Mismatch: no removal.
995            assert!(map.remove_entry_by_keys(&2, "foo").is_none());
996        }
997    }
998
999    mod iter {
1000        use super::*;
1001
1002        #[test]
1003        fn iter() {
1004            let map = populated();
1005            let mut entries: Vec<_> = map
1006                .iter()
1007                .map(|(k1, k2, v)| (*k1, k2.clone(), *v))
1008                .collect();
1009            entries.sort_by_key(|(k1, _, _)| *k1);
1010            assert_eq!(
1011                entries,
1012                vec![(1, "foo".to_string(), 10), (2, "bar".to_string(), 20)]
1013            );
1014        }
1015
1016        #[test]
1017        fn iter_mut() {
1018            let mut map = populated();
1019            // Uses `IntoIterator for &mut DoubleMap`, which delegates to `iter_mut`.
1020            for (_, _, v) in &mut map {
1021                *v *= 10;
1022            }
1023            assert_eq!(map.get_by_key1(&1), Some(&100));
1024            assert_eq!(map.get_by_key1(&2), Some(&200));
1025        }
1026
1027        #[test]
1028        fn for_shared_ref() {
1029            let map = populated();
1030            let mut count = 0;
1031            for (_, _, _) in &map {
1032                count += 1;
1033            }
1034            assert_eq!(count, 2);
1035        }
1036
1037        #[test]
1038        fn keys() {
1039            let map = populated();
1040            let mut keys: Vec<_> = map.keys().map(|(k1, k2)| (*k1, k2.clone())).collect();
1041            keys.sort_by_key(|(k1, _)| *k1);
1042            assert_eq!(keys, vec![(1, "foo".to_string()), (2, "bar".to_string())]);
1043        }
1044
1045        #[test]
1046        fn values() {
1047            let map = populated();
1048            let mut values: Vec<_> = map.values().copied().collect();
1049            values.sort();
1050            assert_eq!(values, vec![10, 20]);
1051        }
1052
1053        #[test]
1054        fn values_mut() {
1055            let mut map = populated();
1056            for v in map.values_mut() {
1057                *v += 1;
1058            }
1059            assert_eq!(map.get_by_key1(&1), Some(&11));
1060        }
1061
1062        #[test]
1063        fn into_iter() {
1064            let mut collected: Vec<_> = populated().into_iter().collect();
1065            collected.sort_by_key(|(k1, _, _)| *k1);
1066            assert_eq!(
1067                collected,
1068                vec![(1, "foo".to_string(), 10), (2, "bar".to_string(), 20)]
1069            );
1070        }
1071
1072        #[test]
1073        fn into_keys() {
1074            let mut keys: Vec<_> = populated().into_keys().collect();
1075            keys.sort_by_key(|(k1, _)| *k1);
1076            assert_eq!(keys, vec![(1, "foo".to_string()), (2, "bar".to_string())]);
1077        }
1078
1079        #[test]
1080        fn into_values() {
1081            let mut values: Vec<_> = populated().into_values().collect();
1082            values.sort();
1083            assert_eq!(values, vec![10, 20]);
1084        }
1085
1086        #[test]
1087        fn iter_clone_and_size_hint() {
1088            let map = populated();
1089            let it = map.iter();
1090            assert_eq!(it.len(), 2);
1091            assert_eq!(it.size_hint(), (2, Some(2)));
1092
1093            let it2 = it.clone();
1094            let mut a: Vec<_> = it.map(|(k1, _, _)| *k1).collect();
1095            let mut b: Vec<_> = it2.map(|(k1, _, _)| *k1).collect();
1096            a.sort();
1097            b.sort();
1098            assert_eq!(a, b);
1099            assert_eq!(a, vec![1, 2]);
1100        }
1101
1102        #[test]
1103        fn keys_values_clone() {
1104            let map = populated();
1105
1106            let keys = map.keys();
1107            let keys2 = keys.clone();
1108            assert_eq!(keys.len(), 2);
1109            let mut a: Vec<_> = keys.map(|(k1, _)| *k1).collect();
1110            let mut b: Vec<_> = keys2.map(|(k1, _)| *k1).collect();
1111            a.sort();
1112            b.sort();
1113            assert_eq!(a, b);
1114
1115            let values = map.values();
1116            let values2 = values.clone();
1117            assert_eq!(values.len(), 2);
1118            let mut a: Vec<_> = values.copied().collect();
1119            let mut b: Vec<_> = values2.copied().collect();
1120            a.sort();
1121            b.sort();
1122            assert_eq!(a, b);
1123        }
1124
1125        #[test]
1126        fn size_hints() {
1127            let mut map = populated();
1128            assert_eq!(map.iter_mut().len(), 2);
1129            assert_eq!(map.iter_mut().size_hint(), (2, Some(2)));
1130            assert_eq!(map.values_mut().len(), 2);
1131            assert_eq!(map.values_mut().size_hint(), (2, Some(2)));
1132
1133            // Drain consumes the map; use a fresh clone.
1134            let mut drain_src = map.clone();
1135            let drain = drain_src.drain();
1136            assert_eq!(drain.len(), 2);
1137            assert_eq!(drain.size_hint(), (2, Some(2)));
1138
1139            assert_eq!(map.clone().into_iter().len(), 2);
1140            assert_eq!(map.clone().into_keys().len(), 2);
1141            assert_eq!(map.into_values().len(), 2);
1142        }
1143    }
1144
1145    mod entry {
1146        use super::*;
1147
1148        #[test]
1149        fn entry() {
1150            let mut map = populated();
1151
1152            // Occupied: both keys identify the same entry.
1153            match map.entry(1, "foo".to_string()).unwrap() {
1154                Entry::Occupied(mut occ) => {
1155                    assert_eq!(*occ.get(), 10);
1156                    *occ.get_mut() = 42;
1157                    let old = occ.insert(7);
1158                    assert_eq!(old, 42);
1159                    assert_eq!(occ.remove_entry(), (1, "foo".to_string(), 7));
1160                }
1161                Entry::Vacant(_) => panic!("expected Occupied"),
1162            }
1163            assert!(!map.contains_key1(&1));
1164
1165            // Vacant: neither key is present.
1166            match map.entry(3, "baz".to_string()).unwrap() {
1167                Entry::Vacant(vac) => {
1168                    assert_eq!(*vac.key1(), 3);
1169                    assert_eq!(vac.key2(), "baz");
1170                    vac.insert(30);
1171                }
1172                Entry::Occupied(_) => panic!("expected Vacant"),
1173            }
1174            assert_eq!(map.get_by_key1(&3), Some(&30));
1175
1176            // Err: key1 clashes with a different key2.
1177            assert!(matches!(
1178                map.entry(2, "quux".to_string()),
1179                Err(KeyConflictError::Key1Exists(2, _, _))
1180            ));
1181
1182            // Err: key2 clashes with a different key1.
1183            assert!(matches!(
1184                map.entry(99, "bar".to_string()),
1185                Err(KeyConflictError::Key2Exists(99, _, _))
1186            ));
1187
1188            // Err: both keys present in different entries.
1189            assert!(matches!(
1190                map.entry(2, "baz".to_string()),
1191                Err(KeyConflictError::BothKeysExist(2, _, _))
1192            ));
1193        }
1194
1195        #[test]
1196        fn key_accessors() {
1197            let mut map = populated();
1198
1199            // Occupied branch.
1200            let e = map.entry(1, "foo".to_string()).unwrap();
1201            assert_eq!(*e.key1(), 1);
1202            assert_eq!(e.key2(), "foo");
1203            let (k1, k2) = e.keys();
1204            assert_eq!((*k1, k2.as_str()), (1, "foo"));
1205
1206            // Vacant branch.
1207            let e = map.entry(3, "baz".to_string()).unwrap();
1208            assert_eq!(*e.key1(), 3);
1209            assert_eq!(e.key2(), "baz");
1210            let (k1, k2) = e.keys();
1211            assert_eq!((*k1, k2.as_str()), (3, "baz"));
1212        }
1213
1214        #[test]
1215        fn or_insert() {
1216            let mut map = fresh();
1217
1218            // Vacant: inserts and returns a mutable reference.
1219            let v = map.entry(1, "foo".to_string()).unwrap().or_insert(10);
1220            *v = 42;
1221            assert_eq!(map.get_by_key1(&1), Some(&42));
1222
1223            // Occupied: returns existing value, does not overwrite.
1224            let v = map.entry(1, "foo".to_string()).unwrap().or_insert(99);
1225            assert_eq!(*v, 42);
1226        }
1227
1228        #[test]
1229        fn or_insert_with() {
1230            let mut map = populated();
1231
1232            // Occupied: closure must not run.
1233            let v = map
1234                .entry(1, "foo".to_string())
1235                .unwrap()
1236                .or_insert_with(|| panic!("closure should not run on Occupied"));
1237            assert_eq!(*v, 10);
1238
1239            // Vacant: closure runs, value is inserted.
1240            let v = map
1241                .entry(3, "baz".to_string())
1242                .unwrap()
1243                .or_insert_with(|| 30);
1244            assert_eq!(*v, 30);
1245            assert_eq!(map.get_by_key1(&3), Some(&30));
1246        }
1247
1248        #[test]
1249        fn or_insert_with_keys() {
1250            let mut map = populated();
1251
1252            // Occupied: closure must not run.
1253            let v = map
1254                .entry(1, "foo".to_string())
1255                .unwrap()
1256                .or_insert_with_keys(|_, _| panic!("closure should not run on Occupied"));
1257            assert_eq!(*v, 10);
1258
1259            // Vacant: closure sees the keys.
1260            let v = map
1261                .entry(3, "baz".to_string())
1262                .unwrap()
1263                .or_insert_with_keys(|k1, k2| *k1 as i32 + k2.len() as i32);
1264            assert_eq!(*v, 3 + 3);
1265        }
1266
1267        #[test]
1268        fn or_default() {
1269            let mut map: DoubleMap<u64, String, i32> = fresh();
1270            let v = map.entry(1, "foo".to_string()).unwrap().or_default();
1271            assert_eq!(*v, 0);
1272        }
1273
1274        #[test]
1275        fn and_modify() {
1276            let mut map = populated();
1277
1278            // Occupied: closure runs.
1279            map.entry(1, "foo".to_string())
1280                .unwrap()
1281                .and_modify(|v| *v *= 2)
1282                .or_insert(0);
1283            assert_eq!(map.get_by_key1(&1), Some(&20));
1284
1285            // Vacant: closure is a no-op, or_insert inserts.
1286            map.entry(3, "baz".to_string())
1287                .unwrap()
1288                .and_modify(|v| *v *= 2)
1289                .or_insert(5);
1290            assert_eq!(map.get_by_key1(&3), Some(&5));
1291        }
1292
1293        #[test]
1294        fn insert_entry() {
1295            let mut map = populated();
1296
1297            // Occupied: overwrites in place.
1298            let occ = map.entry(1, "foo".to_string()).unwrap().insert_entry(42);
1299            assert_eq!(*occ.get(), 42);
1300            assert_eq!(map.get_by_key1(&1), Some(&42));
1301
1302            // Vacant: inserts fresh entry.
1303            let occ = map.entry(3, "baz".to_string()).unwrap().insert_entry(30);
1304            assert_eq!(*occ.get(), 30);
1305            assert_eq!(map.get_by_key1(&3), Some(&30));
1306            assert_eq!(map.get_by_key2("baz"), Some(&30));
1307        }
1308
1309        #[test]
1310        fn vacant_into_keys() {
1311            let mut map = fresh();
1312            let (k1, k2) = match map.entry(1u64, "foo".to_string()).unwrap() {
1313                Entry::Vacant(v) => v.into_keys(),
1314                Entry::Occupied(_) => panic!("expected Vacant"),
1315            };
1316            assert_eq!((k1, k2.as_str()), (1, "foo"));
1317            // into_keys does not insert — map is still empty.
1318            assert!(map.is_empty());
1319        }
1320
1321        #[test]
1322        fn vacant_insert_entry() {
1323            let mut map = fresh();
1324            match map.entry(1u64, "foo".to_string()).unwrap() {
1325                Entry::Vacant(v) => {
1326                    let occ = v.insert_entry(10);
1327                    assert_eq!(*occ.get(), 10);
1328                }
1329                Entry::Occupied(_) => panic!("expected Vacant"),
1330            }
1331            assert_eq!(map.get_by_key1(&1), Some(&10));
1332            assert_eq!(map.get_by_key2("foo"), Some(&10));
1333        }
1334
1335        #[test]
1336        fn occupied_accessors() {
1337            let mut map = populated();
1338            match map.entry(1u64, "foo".to_string()).unwrap() {
1339                Entry::Occupied(occ) => {
1340                    assert_eq!(*occ.key1(), 1);
1341                    assert_eq!(occ.key2(), "foo");
1342                    let (k1, k2) = occ.keys();
1343                    assert_eq!((*k1, k2.as_str()), (1, "foo"));
1344                }
1345                Entry::Vacant(_) => panic!("expected Occupied"),
1346            }
1347        }
1348
1349        #[test]
1350        fn occupied_remove() {
1351            let mut map = populated();
1352            match map.entry(1u64, "foo".to_string()).unwrap() {
1353                Entry::Occupied(occ) => assert_eq!(occ.remove(), 10),
1354                Entry::Vacant(_) => panic!("expected Occupied"),
1355            }
1356            assert!(!map.contains_key1(&1));
1357            assert!(!map.contains_key2("foo"));
1358            assert_eq!(map.len(), 1);
1359        }
1360    }
1361
1362    mod traits {
1363        use super::*;
1364
1365        #[test]
1366        fn from() {
1367            // Conflicting triples are silently skipped.
1368            let map: DoubleMap<u64, String, i32> = DoubleMap::from([
1369                (1, "foo".to_string(), 10),
1370                (2, "bar".to_string(), 20),
1371                (1, "zzz".to_string(), 99),
1372            ]);
1373            assert_eq!(map.len(), 2);
1374            assert_eq!(map.get_by_key1(&1), Some(&10));
1375            assert!(!map.contains_key2("zzz"));
1376        }
1377
1378        #[test]
1379        fn from_iter() {
1380            let map: DoubleMap<u64, String, i32> =
1381                vec![(1u64, "foo".to_string(), 10), (2u64, "bar".to_string(), 20)]
1382                    .into_iter()
1383                    .collect();
1384            assert_eq!(map.len(), 2);
1385            assert_eq!(map.get_by_key1(&1), Some(&10));
1386        }
1387
1388        #[test]
1389        fn extend() {
1390            let mut map = fresh();
1391            map.insert(1, "foo".to_string(), 10).unwrap();
1392
1393            // Conflicting triples are silently skipped; consistent repeats update the value.
1394            map.extend(vec![
1395                (2, "bar".to_string(), 20),
1396                (1, "zzz".to_string(), 99),
1397                (1, "foo".to_string(), 42),
1398            ]);
1399            assert_eq!(map.len(), 2);
1400            assert_eq!(map.get_by_key1(&1), Some(&42));
1401            assert_eq!(map.get_by_key1(&2), Some(&20));
1402            assert!(!map.contains_key2("zzz"));
1403        }
1404
1405        #[test]
1406        fn extend_borrowed() {
1407            let mut map: DoubleMap<u64, u64, i32> = DoubleMap::new();
1408            let items = [(1u64, 10u64, 100i32), (2, 20, 200)];
1409            map.extend(items.iter().map(|(k1, k2, v)| (k1, k2, v)));
1410            assert_eq!(map.len(), 2);
1411            assert_eq!(map.get_by_key1(&1), Some(&100));
1412            assert_eq!(map.get_by_key2(&20), Some(&200));
1413        }
1414
1415        #[test]
1416        fn index() {
1417            let map = populated();
1418            assert_eq!(map[&1], 10);
1419            assert_eq!(map[&2], 20);
1420        }
1421
1422        #[test]
1423        #[should_panic(expected = "no entry found for key")]
1424        fn index_panics() {
1425            let _ = fresh()[&1];
1426        }
1427
1428        #[test]
1429        fn clone() {
1430            let cloned = populated().clone();
1431            assert_eq!(cloned.len(), 2);
1432            assert_eq!(cloned.get_by_key1(&1), Some(&10));
1433            assert_eq!(cloned.get_by_key2("bar"), Some(&20));
1434        }
1435
1436        #[test]
1437        fn clone_from() {
1438            let mut target = fresh();
1439            target.insert(99, "old".to_string(), 999).unwrap();
1440            target.clone_from(&populated());
1441            assert_eq!(target.len(), 2);
1442            assert_eq!(target.get_by_key1(&1), Some(&10));
1443            assert!(!target.contains_key1(&99));
1444            assert!(!target.contains_key2("old"));
1445        }
1446
1447        #[test]
1448        fn eq() {
1449            let a = populated();
1450
1451            // Insertion order does not matter.
1452            let mut b = fresh();
1453            b.insert(2, "bar".to_string(), 20).unwrap();
1454            b.insert(1, "foo".to_string(), 10).unwrap();
1455            assert_eq!(a, b);
1456
1457            // Differing value.
1458            let mut c = fresh();
1459            c.insert(1, "foo".to_string(), 10).unwrap();
1460            c.insert(2, "bar".to_string(), 99).unwrap();
1461            assert_ne!(a, c);
1462        }
1463
1464        #[test]
1465        fn debug_fmt() {
1466            let mut map = fresh();
1467            map.insert(1, "foo".to_string(), 10).unwrap();
1468            let s = format!("{:?}", map);
1469            assert!(s.contains('1'));
1470            assert!(s.contains("foo"));
1471            assert!(s.contains("10"));
1472        }
1473    }
1474
1475    mod errors {
1476        use super::*;
1477
1478        #[test]
1479        fn key_conflict_display() {
1480            let e1: KeyConflictError<u64, String> = KeyConflictError::Key1Exists(1, "a".into(), ());
1481            let e2: KeyConflictError<u64, String> = KeyConflictError::Key2Exists(1, "a".into(), ());
1482            let e3: KeyConflictError<u64, String> =
1483                KeyConflictError::BothKeysExist(1, "a".into(), ());
1484            assert!(e1.to_string().contains("key 1"));
1485            assert!(e2.to_string().contains("key 2"));
1486            assert!(e3.to_string().contains("both"));
1487        }
1488    }
1489}