Skip to main content

linked_hash_table/
map.rs

1//! [`LinkedHashMap`] struct and all its `impl` blocks.
2
3use std::borrow::Borrow;
4use std::fmt;
5use std::hash::{BuildHasher, Hash, RandomState};
6use std::marker::PhantomData;
7use std::mem::MaybeUninit;
8use std::ops::{Index, IndexMut};
9use std::ptr::NonNull;
10
11use hashbrown::HashTable;
12
13use crate::iter::{Drain, IntoIter, Iter, IterMut, Keys, Values, ValuesMut};
14use crate::node::Node;
15
16/// Computes the hash of `key` using the supplied `hash_builder`.
17#[inline]
18fn make_hash<Q, S>(hash_builder: &S, key: &Q) -> u64
19where
20    Q: Hash + ?Sized,
21    S: BuildHasher,
22{
23    hash_builder.hash_one(key)
24}
25
26/// A hash map that preserves **insertion order** and exposes a
27/// [`VecDeque`]-like API with [`insert_back`], [`insert_front`],
28/// [`pop_front`], [`pop_back`], [`front`], and [`back`].
29///
30/// All the usual [`HashMap`] operations (`get`, `get_mut`, `remove`,
31/// `contains_key`, `len`, `is_empty`, `clear`, …) are also available.
32///
33/// ## Ordering contract
34///
35/// * [`insert_back`] and [`insert_front`] **preserve the position** of an
36///   existing key: only the value is updated in-place.  Use
37///   [`move_to_back`] / [`move_to_front`] to explicitly reorder an entry.
38pub struct LinkedHashMap<K, V, S = RandomState> {
39    /// Sentinel head; `head.next` is the first real node (or `tail` if empty).
40    head: NonNull<Node<K, V>>,
41    /// Sentinel tail; `tail.prev` is the last real node (or `head` if empty).
42    tail: NonNull<Node<K, V>>,
43    /// Raw hash table that stores *pointers* to nodes.
44    ///
45    /// The key is stored only in the node itself; no bitwise copy of `K` is
46    /// ever made for the table.  This is why `K` does not need `Clone`/`Copy`.
47    table: HashTable<NonNull<Node<K, V>>>,
48    /// Hasher builder kept separately from the table so it can be borrowed
49    /// independently (required for the `insert` + rehash closure pattern).
50    hash_builder: S,
51}
52
53/// A view into a single entry in a map, similar to
54/// [`std::collections::hash_map::Entry`].
55pub enum Entry<'a, K, V, S = RandomState> {
56    Occupied(OccupiedEntry<'a, K, V, S>),
57    Vacant(VacantEntry<'a, K, V, S>),
58}
59
60/// A view into an occupied entry in a [`LinkedHashMap`].
61pub struct OccupiedEntry<'a, K, V, S = RandomState> {
62    map: &'a mut LinkedHashMap<K, V, S>,
63    node_ptr: NonNull<Node<K, V>>,
64}
65
66/// A view into a vacant entry in a [`LinkedHashMap`].
67pub struct VacantEntry<'a, K, V, S = RandomState> {
68    map: &'a mut LinkedHashMap<K, V, S>,
69    key: K,
70    /// Cached hash of `key` to avoid recomputing it during insertion.
71    cached_hash: u64,
72}
73
74impl<'a, K, V, S> Entry<'a, K, V, S>
75where
76    K: Hash + Eq,
77    S: BuildHasher,
78{
79    /// Returns a reference to this entry's key.
80    pub fn key(&self) -> &K {
81        match self {
82            Entry::Occupied(e) => e.key(),
83            Entry::Vacant(e) => e.key(),
84        }
85    }
86
87    /// Ensures a value is in the entry by inserting `default` if vacant,
88    /// and returns a mutable reference to the value in the entry.
89    pub fn or_insert(self, default: V) -> &'a mut V {
90        match self {
91            Entry::Occupied(e) => e.into_mut(),
92            Entry::Vacant(e) => e.insert(default),
93        }
94    }
95
96    /// Ensures a value is in the entry by inserting the result of `default`
97    /// if vacant, and returns a mutable reference to the value in the entry.
98    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
99        match self {
100            Entry::Occupied(e) => e.into_mut(),
101            Entry::Vacant(e) => e.insert(default()),
102        }
103    }
104
105    /// Ensures a value is in the entry by inserting [`Default::default`]
106    /// if vacant, and returns a mutable reference to the value in the entry.
107    pub fn or_default(self) -> &'a mut V
108    where
109        V: Default,
110    {
111        self.or_insert_with(V::default)
112    }
113
114    /// Provides in-place mutable access to an occupied entry before any
115    /// potential insertion.
116    pub fn and_modify<F: FnOnce(&mut V)>(self, f: F) -> Self {
117        match self {
118            Entry::Occupied(mut e) => {
119                f(e.get_mut());
120                Entry::Occupied(e)
121            }
122            Entry::Vacant(e) => Entry::Vacant(e),
123        }
124    }
125}
126
127impl<'a, K, V, S> OccupiedEntry<'a, K, V, S>
128where
129    K: Hash + Eq,
130    S: BuildHasher,
131{
132    /// Gets a reference to the key in the entry.
133    #[inline]
134    pub fn key(&self) -> &K {
135        // SAFETY: `node_ptr` points to a live node currently indexed by map.
136        unsafe { Node::key_ref(self.node_ptr.as_ptr()) }
137    }
138
139    /// Gets a reference to the value in the entry.
140    #[inline]
141    pub fn get(&self) -> &V {
142        // SAFETY: `node_ptr` points to a live node currently indexed by map.
143        unsafe { Node::value_ref(self.node_ptr.as_ptr()) }
144    }
145
146    /// Gets a mutable reference to the value in the entry.
147    #[inline]
148    pub fn get_mut(&mut self) -> &mut V {
149        // SAFETY: `OccupiedEntry` holds exclusive access to the map.
150        unsafe { Node::value_mut(self.node_ptr.as_ptr()) }
151    }
152
153    /// Converts the entry into a mutable reference to the value.
154    #[inline]
155    pub fn into_mut(self) -> &'a mut V {
156        // SAFETY: Consuming self preserves exclusive access tied to `'a`.
157        unsafe { Node::value_mut(self.node_ptr.as_ptr()) }
158    }
159
160    /// Sets the value of the entry and returns the old value.
161    #[inline]
162    pub fn insert(&mut self, value: V) -> V {
163        std::mem::replace(self.get_mut(), value)
164    }
165
166    /// Removes the entry from the map and returns the value.
167    #[inline]
168    pub fn remove(self) -> V {
169        self.remove_entry().1
170    }
171
172    /// Removes the entry from the map and returns the key-value pair.
173    #[inline]
174    pub fn remove_entry(self) -> (K, V) {
175        let map = self.map;
176        let node = self.node_ptr.as_ptr();
177        // SAFETY: `node` is live and belongs to `map`.
178        unsafe {
179            let hash = make_hash(&map.hash_builder, Node::key_ref(node));
180            let bucket = map
181                .table
182                .find_entry(hash, |ptr| std::ptr::eq(ptr.as_ptr(), node))
183                .expect("LinkedHashMap invariant violated: occupied entry missing from table");
184            bucket.remove();
185            LinkedHashMap::<K, V, S>::unlink(node);
186            let k = Node::key_read(node);
187            let v = Node::value_read(node);
188            let _ = Box::from_raw(node);
189            (k, v)
190        }
191    }
192}
193
194impl<'a, K, V, S> VacantEntry<'a, K, V, S>
195where
196    K: Hash + Eq,
197    S: BuildHasher,
198{
199    /// Gets a reference to the key that would be used when inserting.
200    pub fn key(&self) -> &K {
201        &self.key
202    }
203
204    /// Takes ownership of the key.
205    pub fn into_key(self) -> K {
206        self.key
207    }
208
209    /// Inserts the value into the map and returns a mutable reference to it.
210    pub fn insert(self, value: V) -> &'a mut V {
211        let map = self.map;
212        let hash = self.cached_hash;
213        let node_ptr = Node::new(self.key, value);
214        // SAFETY: append before tail sentinel.
215        unsafe {
216            let before_tail = (*map.tail.as_ptr()).prev;
217            LinkedHashMap::<K, V, S>::link_after(before_tail, node_ptr.as_ptr());
218        }
219        let hash_builder = &map.hash_builder;
220        map.table.insert_unique(hash, node_ptr, |ptr| {
221            let k = unsafe { Node::key_ref(ptr.as_ptr()) };
222            make_hash(hash_builder, k)
223        });
224        // SAFETY: node was just inserted and remains live in the map.
225        unsafe { Node::value_mut(node_ptr.as_ptr()) }
226    }
227}
228
229// SAFETY: LinkedHashMap owns all the nodes it points to.  They are allocated
230// by Node::new / Node::sentinel and freed only by the Drop impl or by the
231// various remove / pop / drain methods that take &mut self.
232// A shared reference (&LinkedHashMap) only gives out shared references to
233// node data; a mutable reference (&mut LinkedHashMap) gives exclusive access.
234// RawTable<NonNull<…>> is !Send/!Sync because NonNull is, but the same
235// reasoning as for Box<Node<K,V>> applies: we have full ownership.
236unsafe impl<K: Send, V: Send, S: Send> Send for LinkedHashMap<K, V, S> {}
237unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LinkedHashMap<K, V, S> {}
238
239impl<K, V> LinkedHashMap<K, V> {
240    /// Creates an empty `LinkedHashMap`.
241    pub fn new() -> Self {
242        Self::with_hasher(RandomState::new())
243    }
244
245    /// Creates an empty `LinkedHashMap` with the specified initial capacity.
246    pub fn with_capacity(capacity: usize) -> Self {
247        Self::with_capacity_and_hasher(capacity, RandomState::new())
248    }
249}
250
251impl<K, V, S> LinkedHashMap<K, V, S> {
252    /// Creates an empty `LinkedHashMap` using the supplied hasher builder.
253    pub fn with_hasher(hash_builder: S) -> Self {
254        Self::with_capacity_and_hasher(0, hash_builder)
255    }
256
257    /// Creates an empty `LinkedHashMap` with the given capacity and hasher.
258    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
259        let head = Node::sentinel();
260        let tail = Node::sentinel();
261
262        // SAFETY: Both sentinel pointers are freshly allocated and valid.
263        // We wire them together so head.next == tail and tail.prev == head,
264        // representing an empty list.
265        unsafe {
266            head.as_ptr().write(Node {
267                key: MaybeUninit::uninit(),
268                value: MaybeUninit::uninit(),
269                prev: std::ptr::null_mut(),
270                next: tail.as_ptr(),
271            });
272            tail.as_ptr().write(Node {
273                key: MaybeUninit::uninit(),
274                value: MaybeUninit::uninit(),
275                prev: head.as_ptr(),
276                next: std::ptr::null_mut(),
277            });
278        }
279
280        Self {
281            head,
282            tail,
283            table: HashTable::with_capacity(capacity),
284            hash_builder,
285        }
286    }
287
288    /// Returns the number of key-value pairs in the map.
289    #[inline]
290    pub fn len(&self) -> usize {
291        self.table.len()
292    }
293
294    /// Returns `true` if the map contains no key-value pairs.
295    #[inline]
296    pub fn is_empty(&self) -> bool {
297        self.table.is_empty()
298    }
299
300    /// Returns the number of elements the map can hold without reallocating.
301    #[inline]
302    pub fn capacity(&self) -> usize {
303        self.table.capacity()
304    }
305
306    /// Returns a reference to the map's [`BuildHasher`].
307    #[inline]
308    pub fn hasher(&self) -> &S {
309        &self.hash_builder
310    }
311
312    /// Removes `node` from the doubly-linked list without freeing its memory.
313    ///
314    /// # Safety
315    ///
316    /// `node` must be a currently-linked, non-sentinel real node.
317    #[inline]
318    unsafe fn unlink(node: *mut Node<K, V>) {
319        // SAFETY: node is non-null, properly aligned, and still wired into the
320        // list, so dereferencing prev/next is valid.
321        unsafe {
322            let prev = (*node).prev;
323            let next = (*node).next;
324            (*prev).next = next;
325            (*next).prev = prev;
326        }
327    }
328
329    /// Inserts `node` into the doubly-linked list immediately after `prev`.
330    ///
331    /// # Safety
332    ///
333    /// Both `node` and `prev` must be valid non-null pointers.  `prev.next`
334    /// must also be a valid pointer (at minimum the tail sentinel).
335    #[inline]
336    unsafe fn link_after(prev: *mut Node<K, V>, node: *mut Node<K, V>) {
337        // SAFETY: prev, node, and prev.next are all valid pointers.
338        unsafe {
339            let next = (*prev).next;
340            (*node).prev = prev;
341            (*node).next = next;
342            (*prev).next = node;
343            (*next).prev = node;
344        }
345    }
346}
347
348impl<K, V, S> LinkedHashMap<K, V, S>
349where
350    K: Hash + Eq,
351    S: BuildHasher,
352{
353    /// Gets the given key's corresponding entry in the map for in-place
354    /// manipulation.
355    pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V, S> {
356        let hash = make_hash(&self.hash_builder, &key);
357        if let Some(&node_ptr) = self
358            .table
359            .find(hash, |ptr| unsafe { Node::key_ref(ptr.as_ptr()) == &key })
360        {
361            Entry::Occupied(OccupiedEntry {
362                map: self,
363                node_ptr,
364            })
365        } else {
366            Entry::Vacant(VacantEntry {
367                map: self,
368                key,
369                cached_hash: hash,
370            })
371        }
372    }
373
374    /// Inserts a key-value pair at the **back** (most-recently-inserted end).
375    ///
376    /// If the key already exists, the value is replaced **in-place** and the
377    /// node's position in the ordering is **preserved** (it is not moved).
378    /// Returns the old value in that case.
379    ///
380    /// To also move the node to the back, call [`move_to_back`] after
381    /// insertion.
382    ///
383    /// [`move_to_back`]: LinkedHashMap::move_to_back
384    pub fn insert_back(&mut self, key: K, value: V) -> Option<V> {
385        let hash = make_hash(&self.hash_builder, &key);
386
387        // Check whether the key is already present.
388        if let Some(node_ptr) = self
389            .table
390            .find(hash, |ptr| unsafe { Node::key_ref(ptr.as_ptr()) == &key })
391            .copied()
392        {
393            // Key already present: update value in-place, preserve position.
394            // `key` is simply dropped here — it is never duplicated.
395            //
396            // SAFETY: node_ptr is a live node; &mut self ensures no other
397            // reference to its value exists simultaneously.
398            unsafe {
399                let old = std::mem::replace(Node::value_mut(node_ptr.as_ptr()), value);
400                return Some(old);
401            }
402        }
403
404        // New key: allocate a node and append before the tail sentinel.
405        // The key lives *only* inside the node — no copy goes into the table.
406        let node_ptr = Node::new(key, value);
407        unsafe {
408            let before_tail = (*self.tail.as_ptr()).prev;
409            Self::link_after(before_tail, node_ptr.as_ptr());
410        }
411        // SAFETY: node_ptr is a valid, fully-initialised node.
412        // The hasher closure is called during rehashing to recompute hashes;
413        // it reads the key directly from the node, so no key duplication occurs.
414        let hash_builder = &self.hash_builder;
415        self.table.insert_unique(hash, node_ptr, |ptr| {
416            let k = unsafe { Node::key_ref(ptr.as_ptr()) };
417            make_hash(hash_builder, k)
418        });
419        None
420    }
421
422    /// Inserts a key-value pair at the **front** (least-recently-inserted end).
423    ///
424    /// If the key already exists, the value is replaced **in-place** and the
425    /// node's position in the ordering is **preserved** (it is not moved).
426    /// Returns the old value in that case.
427    ///
428    /// To also move the node to the front, call [`move_to_front`] after
429    /// insertion.
430    ///
431    /// [`move_to_front`]: LinkedHashMap::move_to_front
432    pub fn insert_front(&mut self, key: K, value: V) -> Option<V> {
433        let hash = make_hash(&self.hash_builder, &key);
434
435        if let Some(node_ptr) = self
436            .table
437            .find(hash, |ptr| unsafe { Node::key_ref(ptr.as_ptr()) == &key })
438            .copied()
439        {
440            // Key already present: update in-place, preserve position.
441            unsafe {
442                let old = std::mem::replace(Node::value_mut(node_ptr.as_ptr()), value);
443                return Some(old);
444            }
445        }
446
447        let node_ptr = Node::new(key, value);
448        unsafe {
449            Self::link_after(self.head.as_ptr(), node_ptr.as_ptr());
450        }
451        let hash_builder = &self.hash_builder;
452        self.table.insert_unique(hash, node_ptr, |ptr| {
453            let k = unsafe { Node::key_ref(ptr.as_ptr()) };
454            make_hash(hash_builder, k)
455        });
456        None
457    }
458
459    /// Alias for [`insert_back`]: matches the [`HashMap::insert`] signature.
460    ///
461    /// [`insert_back`]: LinkedHashMap::insert_back
462    /// [`HashMap::insert`]: std::collections::HashMap::insert
463    #[inline]
464    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
465        self.insert_back(key, value)
466    }
467
468    /// Returns a reference to the value associated with `key`, if present.
469    pub fn get<Q>(&self, key: &Q) -> Option<&V>
470    where
471        K: Borrow<Q>,
472        Q: Hash + Eq + ?Sized,
473    {
474        let hash = make_hash(&self.hash_builder, key);
475        self.table
476            .find(hash, |ptr| unsafe {
477                Node::key_ref(ptr.as_ptr()).borrow() == key
478            })
479            .map(|ptr| unsafe { Node::value_ref(ptr.as_ptr()) })
480    }
481
482    /// Returns a mutable reference to the value associated with `key`, if
483    /// present.
484    pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
485    where
486        K: Borrow<Q>,
487        Q: Hash + Eq + ?Sized,
488    {
489        let hash = make_hash(&self.hash_builder, key);
490        // Obtain a copy of the node pointer (table.get takes &self.table);
491        // then use &mut self to justify the exclusive &mut V.
492        let ptr = self
493            .table
494            .find(hash, |ptr| unsafe {
495                Node::key_ref(ptr.as_ptr()).borrow() == key
496            })
497            .copied()?;
498        // SAFETY: We hold &mut self; no other reference to this value exists.
499        Some(unsafe { Node::value_mut(ptr.as_ptr()) })
500    }
501
502    /// Returns `(&key, &value)` for the given key, if present.
503    pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
504    where
505        K: Borrow<Q>,
506        Q: Hash + Eq + ?Sized,
507    {
508        let hash = make_hash(&self.hash_builder, key);
509        self.table
510            .find(hash, |ptr| unsafe {
511                Node::key_ref(ptr.as_ptr()).borrow() == key
512            })
513            .map(|ptr| unsafe {
514                let node = ptr.as_ptr();
515                (Node::key_ref(node), Node::value_ref(node))
516            })
517    }
518
519    /// Returns `true` if the map contains a value for `key`.
520    #[inline]
521    pub fn contains_key<Q>(&self, key: &Q) -> bool
522    where
523        K: Borrow<Q>,
524        Q: Hash + Eq + ?Sized,
525    {
526        let hash = make_hash(&self.hash_builder, key);
527        self.table
528            .find(hash, |ptr| unsafe {
529                Node::key_ref(ptr.as_ptr()).borrow() == key
530            })
531            .is_some()
532    }
533
534    /// Returns references to the **front** (oldest inserted) key-value pair,
535    /// or `None` if the map is empty.
536    pub fn front(&self) -> Option<(&K, &V)> {
537        // SAFETY: head is a valid sentinel.  If the list is non-empty,
538        // head.next is a live real node.
539        unsafe {
540            let first = (*self.head.as_ptr()).next;
541            if first == self.tail.as_ptr() {
542                return None;
543            }
544            Some((Node::key_ref(first), Node::value_ref(first)))
545        }
546    }
547
548    /// Returns a mutable reference to the **front** key-value pair, or `None`.
549    pub fn front_mut(&mut self) -> Option<(&K, &mut V)> {
550        // SAFETY: &mut self guarantees exclusive access; no other reference to
551        // the node's value can exist.
552        unsafe {
553            let first = (*self.head.as_ptr()).next;
554            if first == self.tail.as_ptr() {
555                return None;
556            }
557            Some((Node::key_ref(first), Node::value_mut(first)))
558        }
559    }
560
561    /// Returns references to the **back** (most recently inserted) key-value
562    /// pair, or `None` if the map is empty.
563    pub fn back(&self) -> Option<(&K, &V)> {
564        // SAFETY: symmetric to front().
565        unsafe {
566            let last = (*self.tail.as_ptr()).prev;
567            if last == self.head.as_ptr() {
568                return None;
569            }
570            Some((Node::key_ref(last), Node::value_ref(last)))
571        }
572    }
573
574    /// Returns a mutable reference to the **back** key-value pair, or `None`.
575    pub fn back_mut(&mut self) -> Option<(&K, &mut V)> {
576        // SAFETY: &mut self guarantees exclusive access.
577        unsafe {
578            let last = (*self.tail.as_ptr()).prev;
579            if last == self.head.as_ptr() {
580                return None;
581            }
582            Some((Node::key_ref(last), Node::value_mut(last)))
583        }
584    }
585
586    /// Removes and returns the **front** (oldest) key-value pair, or `None`.
587    pub fn pop_front(&mut self) -> Option<(K, V)> {
588        // SAFETY: If the list is non-empty, head.next is a valid real node.
589        unsafe {
590            let first = (*self.head.as_ptr()).next;
591            if first == self.tail.as_ptr() {
592                return None;
593            }
594            self.remove_node(first)
595        }
596    }
597
598    /// Removes and returns the **back** (newest) key-value pair, or `None`.
599    pub fn pop_back(&mut self) -> Option<(K, V)> {
600        // SAFETY: symmetric to pop_front.
601        unsafe {
602            let last = (*self.tail.as_ptr()).prev;
603            if last == self.head.as_ptr() {
604                return None;
605            }
606            self.remove_node(last)
607        }
608    }
609
610    /// Removes the entry for `key` and returns the value, if present.
611    pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
612    where
613        K: Borrow<Q>,
614        Q: Hash + Eq + ?Sized,
615    {
616        self.remove_entry(key).map(|(_, v)| v)
617    }
618
619    /// Removes the entry for `key` and returns `(key, value)`, if present.
620    pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
621    where
622        K: Borrow<Q>,
623        Q: Hash + Eq + ?Sized,
624    {
625        let hash = make_hash(&self.hash_builder, key);
626        let bucket = self
627            .table
628            .find_entry(hash, |ptr| unsafe {
629                Node::key_ref(ptr.as_ptr()).borrow() == key
630            })
631            .ok()?;
632        let (node_ptr, _) = bucket.remove();
633        unsafe {
634            let node = node_ptr.as_ptr();
635            Self::unlink(node);
636            let k = Node::key_read(node);
637            let v = Node::value_read(node);
638            let _ = Box::from_raw(node);
639            Some((k, v))
640        }
641    }
642
643    /// Removes a node identified by raw pointer from both the hash table and
644    /// the linked list, frees it, and returns its `(K, V)`.
645    ///
646    /// Using pointer identity for the table lookup avoids any borrow of the
647    /// key field across the `remove` call and is faster than a key comparison.
648    ///
649    /// # Safety
650    ///
651    /// `node` must be a live, fully-initialised real node that is currently
652    /// linked in the list and indexed in the hash table.
653    unsafe fn remove_node(&mut self, node: *mut Node<K, V>) -> Option<(K, V)> {
654        unsafe {
655            // Compute the hash from the node's own key.
656            let hash = make_hash(&self.hash_builder, Node::key_ref(node));
657            // Locate the bucket by pointer identity — faster than key equality
658            // and sidesteps any lifetime issue with borrowing the key field.
659            let bucket = self
660                .table
661                .find_entry(hash, |ptr| std::ptr::eq(ptr.as_ptr(), node))
662                .expect("LinkedHashMap invariant violated: node missing from table");
663            bucket.remove();
664            Self::unlink(node);
665            let k = Node::key_read(node);
666            let v = Node::value_read(node);
667            let _ = Box::from_raw(node);
668            Some((k, v))
669        }
670    }
671
672    /// Retains only entries for which `f(&key, &mut value)` returns `true`.
673    /// Elements are visited in **insertion order** (front → back).
674    pub fn retain<F>(&mut self, mut f: F)
675    where
676        F: FnMut(&K, &mut V) -> bool,
677    {
678        // SAFETY: We traverse via raw pointers.  The `next` pointer is saved
679        // before any unlink so the traversal remains valid even after removal.
680        // We use pointer identity for the table lookup to avoid borrowing the
681        // key field across the remove call.
682        unsafe {
683            let mut cur = (*self.head.as_ptr()).next;
684            while cur != self.tail.as_ptr() {
685                let next = (*cur).next;
686                let k = Node::key_ref(cur);
687                let v = Node::value_mut(cur);
688                if !f(k, v) {
689                    // Compute hash while k is still valid, then find by pointer.
690                    let hash = make_hash(&self.hash_builder, k);
691                    let b = self
692                        .table
693                        .find_entry(hash, |ptr| std::ptr::eq(ptr.as_ptr(), cur))
694                        .expect(
695                            "LinkedHashMap invariant violated: retained node missing from table",
696                        );
697                    b.remove();
698                    Self::unlink(cur);
699                    Node::key_drop(cur);
700                    Node::value_drop(cur);
701                    let _ = Box::from_raw(cur);
702                }
703                cur = next;
704            }
705        }
706    }
707
708    /// Removes all key-value pairs from the map.
709    pub fn clear(&mut self) {
710        // SAFETY: We free every real node via Node::drop_real, then restore
711        // the head ↔ tail sentinel linkage to represent an empty list.
712        unsafe {
713            let mut cur = (*self.head.as_ptr()).next;
714            while cur != self.tail.as_ptr() {
715                let next = (*cur).next;
716                Node::drop_real(cur);
717                cur = next;
718            }
719            (*self.head.as_ptr()).next = self.tail.as_ptr();
720            (*self.tail.as_ptr()).prev = self.head.as_ptr();
721        }
722        // Clear the hash table (drops the NonNull<Node> pointers stored in it;
723        // since NonNull has no Drop impl this just marks all slots as empty and
724        // frees any overflow storage — the nodes themselves were freed above).
725        self.table.clear();
726    }
727
728    /// Moves the entry for `key` to the **back** of the ordering.
729    /// Returns `true` if the key was found, `false` otherwise.
730    pub fn move_to_back<Q>(&mut self, key: &Q) -> bool
731    where
732        K: Borrow<Q>,
733        Q: Hash + Eq + ?Sized,
734    {
735        let hash = make_hash(&self.hash_builder, key);
736        if let Some(&node_ptr) = self.table.find(hash, |ptr| unsafe {
737            Node::key_ref(ptr.as_ptr()).borrow() == key
738        }) {
739            // SAFETY: node_ptr is a live node owned by this map.
740            unsafe {
741                let node = node_ptr.as_ptr();
742                Self::unlink(node);
743                let before_tail = (*self.tail.as_ptr()).prev;
744                Self::link_after(before_tail, node);
745            }
746            true
747        } else {
748            false
749        }
750    }
751
752    /// Moves the entry for `key` to the **front** of the ordering.
753    /// Returns `true` if the key was found, `false` otherwise.
754    pub fn move_to_front<Q>(&mut self, key: &Q) -> bool
755    where
756        K: Borrow<Q>,
757        Q: Hash + Eq + ?Sized,
758    {
759        let hash = make_hash(&self.hash_builder, key);
760        if let Some(&node_ptr) = self.table.find(hash, |ptr| unsafe {
761            Node::key_ref(ptr.as_ptr()).borrow() == key
762        }) {
763            // SAFETY: node_ptr is a live node owned by this map.
764            unsafe {
765                let node = node_ptr.as_ptr();
766                Self::unlink(node);
767                Self::link_after(self.head.as_ptr(), node);
768            }
769            true
770        } else {
771            false
772        }
773    }
774
775    /// Removes all elements in **insertion order**, returning `(K, V)` pairs
776    /// via an iterator.  The map is empty after this call (even if the
777    /// iterator is dropped before it is fully consumed).
778    pub fn drain(&mut self) -> Drain<'_, K, V> {
779        // SAFETY: We clear the hash table first (frees its own storage only;
780        // NonNull has no Drop impl so the nodes are NOT freed).  Ownership of
781        // the nodes is transferred to the Drain iterator, which frees them one
782        // by one and restores sentinel linkage in its Drop impl.
783        let front = unsafe { (*self.head.as_ptr()).next };
784        let len = self.len();
785        self.table.clear();
786        Drain {
787            front,
788            tail_ptr: self.tail.as_ptr(),
789            head_ptr: self.head.as_ptr(),
790            len,
791            _marker: PhantomData,
792        }
793    }
794}
795
796impl<K, V, S> LinkedHashMap<K, V, S> {
797    /// Returns an iterator over `(&K, &V)` pairs in **insertion order**.
798    pub fn iter(&self) -> Iter<'_, K, V> {
799        // SAFETY: head and tail are valid sentinels for the lifetime of self.
800        // head.next is either the first real node or the tail sentinel when empty.
801        unsafe {
802            Iter {
803                front: (*self.head.as_ptr()).next,
804                back: (*self.tail.as_ptr()).prev,
805                len: self.len(),
806                _marker: PhantomData,
807            }
808        }
809    }
810
811    /// Returns an iterator over `(&K, &mut V)` pairs in **insertion order**.
812    pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
813        // SAFETY: &mut self guarantees no other reference to the node contents
814        // exists.  Each node is visited exactly once, so no two mutable
815        // references can alias.
816        unsafe {
817            IterMut {
818                front: (*self.head.as_ptr()).next,
819                back: (*self.tail.as_ptr()).prev,
820                len: self.len(),
821                _marker: PhantomData,
822            }
823        }
824    }
825
826    /// Returns an iterator over **keys** in insertion order.
827    pub fn keys(&self) -> Keys<'_, K, V> {
828        Keys { inner: self.iter() }
829    }
830
831    /// Returns an iterator over **values** in insertion order.
832    pub fn values(&self) -> Values<'_, K, V> {
833        Values { inner: self.iter() }
834    }
835
836    /// Returns a mutable iterator over **values** in insertion order.
837    pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
838        ValuesMut {
839            inner: self.iter_mut(),
840        }
841    }
842}
843
844impl<K, V, S> Drop for LinkedHashMap<K, V, S> {
845    fn drop(&mut self) {
846        // SAFETY: We iterate every real node and free it via Node::drop_real,
847        // then free the two sentinel nodes via Node::drop_sentinel (their
848        // key/value are uninitialised and must not be dropped).
849        // The RawTable's own Drop then runs and frees the table's internal
850        // storage; the NonNull pointers it stored have no Drop impl, so the
851        // nodes (already freed above) are not touched again.
852        unsafe {
853            let mut cur = (*self.head.as_ptr()).next;
854            while cur != self.tail.as_ptr() {
855                let next = (*cur).next;
856                Node::drop_real(cur);
857                cur = next;
858            }
859            Node::drop_sentinel(self.head.as_ptr());
860            Node::drop_sentinel(self.tail.as_ptr());
861        }
862    }
863}
864
865impl<K, V, S, Q> Index<&Q> for LinkedHashMap<K, V, S>
866where
867    K: Hash + Eq + Borrow<Q>,
868    Q: Hash + Eq + ?Sized,
869    S: BuildHasher,
870{
871    type Output = V;
872
873    /// Returns a reference to the value for `key`.
874    ///
875    /// # Panics
876    ///
877    /// Panics if `key` is not present in the map.
878    fn index(&self, key: &Q) -> &V {
879        self.get(key).expect("LinkedHashMap: key not found")
880    }
881}
882
883impl<K, V, S, Q> IndexMut<&Q> for LinkedHashMap<K, V, S>
884where
885    K: Hash + Eq + Borrow<Q>,
886    Q: Hash + Eq + ?Sized,
887    S: BuildHasher,
888{
889    /// Returns a mutable reference to the value for `key`.
890    ///
891    /// # Panics
892    ///
893    /// Panics if `key` is not present in the map.
894    fn index_mut(&mut self, key: &Q) -> &mut V {
895        self.get_mut(key).expect("LinkedHashMap: key not found")
896    }
897}
898
899impl<K, V> Default for LinkedHashMap<K, V> {
900    fn default() -> Self {
901        Self::new()
902    }
903}
904
905impl<K, V, S> fmt::Debug for LinkedHashMap<K, V, S>
906where
907    K: fmt::Debug,
908    V: fmt::Debug,
909{
910    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
911        f.debug_map().entries(self.iter()).finish()
912    }
913}
914
915impl<K, V, S1, S2> PartialEq<LinkedHashMap<K, V, S2>> for LinkedHashMap<K, V, S1>
916where
917    K: PartialEq,
918    V: PartialEq,
919{
920    /// Two maps are equal only when they contain **the same key-value pairs in
921    /// the same order**.
922    fn eq(&self, other: &LinkedHashMap<K, V, S2>) -> bool {
923        if self.len() != other.len() {
924            return false;
925        }
926        self.iter()
927            .zip(other.iter())
928            .all(|((k1, v1), (k2, v2))| k1 == k2 && v1 == v2)
929    }
930}
931
932impl<K: PartialEq + Eq, V: Eq, S> Eq for LinkedHashMap<K, V, S> {}
933
934impl<K: Clone + Hash + Eq, V: Clone, S: BuildHasher + Clone> Clone for LinkedHashMap<K, V, S> {
935    fn clone(&self) -> Self {
936        let mut new_map = Self::with_capacity_and_hasher(self.len(), self.hash_builder.clone());
937        for (k, v) in self.iter() {
938            new_map.insert_back(k.clone(), v.clone());
939        }
940        new_map
941    }
942}
943
944impl<K: Hash + Eq, V> FromIterator<(K, V)> for LinkedHashMap<K, V> {
945    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
946        let iter = iter.into_iter();
947        let (lower, _) = iter.size_hint();
948        let mut map = Self::with_capacity(lower);
949        for (k, v) in iter {
950            map.insert_back(k, v);
951        }
952        map
953    }
954}
955
956impl<K: Hash + Eq, V, S: BuildHasher> Extend<(K, V)> for LinkedHashMap<K, V, S> {
957    fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
958        for (k, v) in iter {
959            self.insert_back(k, v);
960        }
961    }
962}
963
964/// Consuming iterator: yields all `(K, V)` pairs in insertion order.
965impl<K, V, S> IntoIterator for LinkedHashMap<K, V, S> {
966    type Item = (K, V);
967    type IntoIter = IntoIter<K, V>;
968
969    fn into_iter(self) -> IntoIter<K, V> {
970        // SAFETY: We must prevent LinkedHashMap::drop from running (it would
971        // free all nodes, causing a double-free in IntoIter::drop).
972        // Strategy: extract the table and hash_builder via ptr::read, then
973        // mem::forget(self) to skip the drop, then drop both fields manually.
974        //   - drop(table): frees the raw table's own storage; the NonNull<Node>
975        //     values stored in it have no Drop impl, so nodes are NOT freed.
976        //   - drop(hash_builder): runs S's destructor (if any).
977        let front = unsafe { (*self.head.as_ptr()).next };
978        let len = self.len();
979        let head = self.head;
980        let tail = self.tail;
981        let table = unsafe { std::ptr::read(&self.table) };
982        let hash_builder = unsafe { std::ptr::read(&self.hash_builder) };
983        std::mem::forget(self);
984        drop(table);
985        drop(hash_builder);
986        IntoIter {
987            front,
988            tail,
989            head,
990            len,
991        }
992    }
993}
994
995/// Shared-reference iterator: yields `(&K, &V)` in insertion order.
996impl<'a, K, V, S> IntoIterator for &'a LinkedHashMap<K, V, S> {
997    type Item = (&'a K, &'a V);
998    type IntoIter = Iter<'a, K, V>;
999
1000    #[inline]
1001    fn into_iter(self) -> Iter<'a, K, V> {
1002        self.iter()
1003    }
1004}
1005
1006/// Mutable-reference iterator: yields `(&K, &mut V)` in insertion order.
1007impl<'a, K, V, S> IntoIterator for &'a mut LinkedHashMap<K, V, S> {
1008    type Item = (&'a K, &'a mut V);
1009    type IntoIter = IterMut<'a, K, V>;
1010
1011    #[inline]
1012    fn into_iter(self) -> IterMut<'a, K, V> {
1013        self.iter_mut()
1014    }
1015}