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}