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