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}