deepmesa_collections/lhmap/lhmap.rs
1/*
2 LinkedHashMap: A fast and flexible linked HashMap that allows for
3 O(1) inserts and removes with a predictable iteration order.
4
5 Copyright 2021 "Rahul Singh <rsingh@arrsingh.com>"
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18*/
19
20use crate::lhmap::entry::Entry;
21use crate::lhmap::entry::EntryHandle;
22use crate::lhmap::entry::Order;
23use crate::lhmap::entry::PtrKey;
24use crate::lhmap::iter::Iter;
25use crate::lhmap::iter::IterMut;
26use crate::lhmap::iter::Keys;
27use crate::lhmap::iter::Values;
28use crate::lhmap::iter::ValuesMut;
29use crate::linkedlist::list::LinkedList;
30use crate::linkedlist::node::NodeHandle;
31use core::hash::Hash;
32use std::collections::HashMap;
33
34/// A fast and flexible LinkedHashMap that combines a [`std::collections::HashMap`] and a
35/// [`LinkedList`](LinkedList) for *O*(*1*) inserts, lookups and deletes along with a
36/// predictable iteration order.
37///
38/// All the basic functions - [`get()`](#method.get),
39/// [`get_mut()`](#method.get_mut),
40/// [`get_key_value()`](#method.get_key_value),
41/// [`put()`](#method.put), [`insert()`](#method.insert),
42/// [`remove()`](#method.remove),
43/// [`remove_entry()`](#method.remove_entry) - provide constant time
44/// performance which is expected to be lower than that of the Hashmap
45/// given the added expense of of maintaining and updating the
46/// underlying linked list.
47///
48/// # Getting Started
49/// ```
50/// use deepmesa_collections::LinkedHashMap;
51/// use deepmesa_collections::lhmap::Order;
52///
53/// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
54/// lhm.put(1, "a");
55/// lhm.put(2, "b");
56///
57/// assert_eq!(lhm.get(&1), Some(&"a"));
58/// assert_eq!(lhm.get(&2), Some(&"b"));
59///
60/// if let Some(val) = lhm.get_mut(&1) {
61/// *val = "d";
62/// }
63///
64/// assert_eq!(lhm.get(&1), Some(&"d"));
65///
66/// ```
67///
68/// # Iteration Order
69///
70/// This map holds a LinkedList of all the elements that defines the
71/// iteration order. The order is either [`InsertionOrder`](Order) or
72/// [`AccessOrder`](Order). InsertionOrder is the order in which the
73/// keys were inserted into the map from least recently inserted
74/// (oldest) to most recently inserted (newest). ReInserting a key
75/// (via the insert or put methods) will change the insertion order to
76/// make the re-inserted key the most recently inserted (newest) in
77/// the order.
78///
79/// AccessOrder is the order in which the keys in the map were last
80/// accessed (via the [`get()`](#method.get),
81/// [`get_key_value()`](#method.get_key_value),
82/// [`get_mut()`](#method.get_mut) methods) from least-recently
83/// accessed (oldest) to most recently accessed (newest). Iterating
84/// over the map using one of the iterators -
85/// [`iter()`](#method.iter), [`iter_mut()`](#method.iter_mut),
86/// [`keys()`](#method.keys), [`values()`](#method.values),
87/// [`values_mut()`](#method.values_mut) - does not affect the order.
88///
89/// Iteration over the map requires time proportional to the length of
90/// the map (*O*(*len*)) regardless of the capacity because it
91/// iterates over the elements of the underlying linked list. The
92/// iteration order of the map is always from oldest entry (accessed
93/// or inserted) to the newest entry (accessed or inserted).
94///
95/// The map offers iterators over the [`elements`](#method.iter),
96/// [`keys`](#method.keys) and [`values`](#method.values) with mutable
97/// iterators for [`elements`](#method.iter_mut) and
98/// [`values`](#method.values_mut). The iterators can also be
99/// reversed.
100///
101/// ```
102/// // Construct a map in InsertionOrder
103/// use deepmesa_collections::LinkedHashMap;
104/// use deepmesa_collections::lhmap::Order;
105///
106/// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
107/// lhm.put(1, "a");
108/// lhm.put(2, "b");
109///
110/// lhm.get(&1);
111///
112/// let mut iter = lhm.iter();
113/// assert_eq!(iter.next(), Some((&1, &"a")));
114/// assert_eq!(iter.next(), Some((&2, &"b")));
115/// assert_eq!(iter.next(), None);
116/// iter = iter.reverse();
117/// assert_eq!(iter.next(), Some((&2, &"b")));
118/// assert_eq!(iter.next(), Some((&1, &"a")));
119/// assert_eq!(iter.next(), None);
120///
121///
122/// // Construct a map in AccessOrder
123/// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
124/// lhm.put(1, "a");
125/// lhm.put(2, "b");
126///
127/// lhm.get(&1);
128///
129/// let mut iter = lhm.iter();
130/// assert_eq!(iter.next(), Some((&2, &"b")));
131/// assert_eq!(iter.next(), Some((&1, &"a")));
132/// assert_eq!(iter.next(), None);
133/// iter = iter.reverse();
134/// assert_eq!(iter.next(), Some((&1, &"a")));
135/// assert_eq!(iter.next(), Some((&2, &"b")));
136/// assert_eq!(iter.next(), None);
137///
138/// ```
139///
140/// # Evicting Elements
141///
142/// The Map also supports construction with an
143/// [`evict_eldest`](#method.new) function that can be provided to
144/// implement a policy for removing entries when new elements are
145/// added to the map. A LinkedHashMap with [`AccessOrder`](Order) and
146/// an eviction function is well suited to building an LRU Cache.
147///
148/// ```
149/// use deepmesa_collections::lhmap::Entry;
150/// pub fn evict<K,V>(len: usize, capacity: usize, e: &Entry<K, V>) -> bool {
151/// if len > capacity {
152/// return true;
153/// }
154/// return false;
155/// }
156///
157/// use deepmesa_collections::LinkedHashMap;
158/// use deepmesa_collections::lhmap::Order;
159///
160/// let mut lhm = LinkedHashMap::<u16, &str>::new(3, Order::AccessOrder, Some(evict));
161/// lhm.put(1, "a");
162/// lhm.put(2, "b");
163/// lhm.put(3, "c");
164///
165/// assert_eq!(lhm.get(&2), Some(&"b"));
166/// lhm.put(4, "d");
167/// assert_eq!(lhm.get(&1), None);
168///
169/// ```
170///
171/// # Head/Tail Semantics
172///
173/// This LinkedHashMap uses the following head/tail semantics:
174/// - **Head**: Contains the oldest elements (least recently inserted/accessed)
175/// - **Tail**: Contains the newest elements (most recently inserted/accessed)
176/// - **Iteration**: Always proceeds from head to tail (oldest to newest)
177/// - **Eviction**: Removes elements from the head (oldest elements first)
178///
179/// New elements are added to the tail, and in AccessOrder mode, accessed
180/// elements are moved to the tail (marking them as most recently used).
181pub struct LinkedHashMap<K, V>
182where
183 K: Hash + Eq,
184{
185 pub(crate) evict_eldest: Option<fn(len: usize, capacity: usize, e: &Entry<K, V>) -> bool>,
186 pub(crate) order: Order,
187 pub(crate) cap: usize,
188 pub(crate) ll: LinkedList<Entry<K, V>>,
189 pub(crate) map: HashMap<PtrKey<K>, NodeHandle<Entry<K, V>>>,
190}
191
192unsafe impl<K, V> Send for LinkedHashMap<K, V> where K: Hash + Eq {}
193unsafe impl<K, V> Sync for LinkedHashMap<K, V> where K: Hash + Eq {}
194
195impl<'a, K, V> IntoIterator for &'a LinkedHashMap<K, V>
196where
197 K: Hash + Eq,
198{
199 type Item = (&'a K, &'a V);
200 type IntoIter = Iter<'a, K, V>;
201 fn into_iter(self) -> Self::IntoIter {
202 self.iter()
203 }
204}
205
206impl<'a, K, V> IntoIterator for &'a mut LinkedHashMap<K, V>
207where
208 K: Hash + Eq,
209{
210 type Item = (&'a K, &'a mut V);
211 type IntoIter = IterMut<'a, K, V>;
212 fn into_iter(self) -> Self::IntoIter {
213 self.iter_mut()
214 }
215}
216
217impl<K, V> LinkedHashMap<K, V>
218where
219 K: Hash + Eq,
220{
221 /// Creates an empty LinkedHashMap with the specified capacity and
222 /// iteration order. The evict_eldest function can be supplied
223 /// that is called everytime a new entry is inserted into the map
224 /// with the current length, capacity and the first entry in the
225 /// linkedlist (least recently inserted or accessed).
226 ///
227 /// # Examples
228 ///
229 /// ```
230 /// use deepmesa_collections::LinkedHashMap;
231 /// use deepmesa_collections::lhmap::Order;
232 /// let lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
233 /// ```
234 pub fn new(
235 capacity: usize,
236 order: Order,
237 evict_eldest: Option<fn(len: usize, capacity: usize, e: &Entry<K, V>) -> bool>,
238 ) -> LinkedHashMap<K, V> {
239 return LinkedHashMap {
240 evict_eldest,
241 order,
242 cap: capacity,
243 map: HashMap::with_capacity(capacity),
244 ll: LinkedList::with_capacity(capacity),
245 };
246 }
247
248 /// Creates an empty LinkedHashMap with the specified capacity and
249 /// InsertionOrder. The underlying list will continue to
250 /// reallocate additional memory by doubling the capacity
251 /// everytime the capacity is exceeded. However the list will not
252 /// deallocate memory when keys are removed.
253 ///
254 /// If the capacity is set to 0, and the underlying list is full,
255 /// then new memory will be allocated for one new element
256 /// everytime an element is added to the list.
257 ///
258 /// The underlying hashmap will only allocate memory if the
259 /// capacity is greater than zero.
260 ///
261 /// # Examples
262 /// ```
263 /// use deepmesa_collections::LinkedHashMap;
264 /// let lhm = LinkedHashMap::<u16, &str>::with_capacity(10);
265 /// assert_eq!(lhm.capacity(), 10);
266 /// assert_eq!(lhm.len(), 0);
267 ///
268 /// ```
269 pub fn with_capacity(capacity: usize) -> LinkedHashMap<K, V> {
270 return Self::new(capacity, Order::InsertionOrder, None);
271 }
272
273 /// Returns the number of elements the map can hold before new
274 /// memory is allocated.
275 ///
276 /// # Examples
277 /// ```
278 /// use deepmesa_collections::LinkedHashMap;
279 /// use deepmesa_collections::lhmap::Order;
280 ///
281 /// let lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
282 /// assert_eq!(10, lhm.capacity());
283 /// assert_eq!(0, lhm.len());
284 /// ```
285 pub fn capacity(&self) -> usize {
286 return self.cap;
287 }
288
289 /// Returns the number or elements in the map.
290 ///
291 /// # Examples
292 /// ```
293 /// use deepmesa_collections::LinkedHashMap;
294 /// use deepmesa_collections::lhmap::Order;
295 ///
296 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
297 /// assert_eq!(lhm.len(), 0);
298 /// lhm.insert(1, "a");
299 /// assert_eq!(lhm.len(), 1);
300 ///
301 /// ```
302 pub fn len(&self) -> usize {
303 return self.map.len();
304 }
305
306 /// Removes and drops all the key-value pairs this map. This has
307 /// no effect on the allocated capacity of the map or the underlying list.
308 ///
309 /// This method should complete in *O*(*n*) time.
310 ///
311 /// # Examples
312 /// ```
313 /// use deepmesa_collections::LinkedHashMap;
314 /// use deepmesa_collections::lhmap::Order;
315 ///
316 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
317 /// lhm.insert(1, "a");
318 /// lhm.clear();
319 /// assert!(lhm.is_empty());
320 ///
321 /// ```
322 pub fn clear(&mut self) {
323 self.map.clear();
324 self.ll.clear();
325 }
326
327 /// Returns true if the map contains no elements and false otherwise.
328 /// This method should complete in *O*(*1*) time.
329 ///
330 /// # Examples
331 /// ```
332 /// use deepmesa_collections::LinkedHashMap;
333 /// use deepmesa_collections::lhmap::Order;
334 ///
335 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
336 /// assert!(lhm.is_empty());
337 /// lhm.insert(1, "a");
338 /// assert!(!lhm.is_empty());
339 ///
340 /// ```
341 pub fn is_empty(&self) -> bool {
342 return self.map.len() == 0;
343 }
344
345 /// Returns true if the map contains a value for the specified
346 /// key. This method should complete in *O*(*1*) time.
347 ///
348 /// # Examples
349 /// ```
350 /// use deepmesa_collections::LinkedHashMap;
351 /// use deepmesa_collections::lhmap::Order;
352 ///
353 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
354 /// lhm.insert(1, "a");
355 /// assert_eq!(lhm.contains_key(&1), true);
356 /// assert_eq!(lhm.contains_key(&2), false);
357 /// ```
358 pub fn contains_key(&self, key: &K) -> bool {
359 return self.map.contains_key(&PtrKey::new(key));
360 }
361
362 /// Returns a handle to the entry corresponding to the key, or None
363 /// if the key is not present in the map.
364 ///
365 /// The returned handle can be used to manipulate the position of the
366 /// entry within the map's iteration order without affecting the
367 /// iteration order of access methods like `get()`, `get_mut()`, etc.
368 ///
369 /// This method should complete in *O*(*1*) time.
370 ///
371 /// # Examples
372 /// ```
373 /// use deepmesa_collections::LinkedHashMap;
374 /// use deepmesa_collections::lhmap::Order;
375 ///
376 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
377 /// lhm.insert(1, "a");
378 /// lhm.insert(2, "b");
379 /// lhm.insert(3, "c");
380 ///
381 /// // Get handle for key 1
382 /// if let Some(handle) = lhm.entry_handle(&1) {
383 /// // Move it to the end of iteration order
384 /// lhm.make_tail(handle);
385 /// }
386 ///
387 /// // Now iteration order will be: 2, 3, 1
388 /// let keys: Vec<_> = lhm.keys().copied().collect();
389 /// assert_eq!(keys, vec![2, 3, 1]);
390 ///
391 /// // Non-existent key returns None
392 /// assert_eq!(lhm.entry_handle(&99), None);
393 /// ```
394 pub fn entry_handle(&self, key: &K) -> Option<EntryHandle<K, V>> {
395 if let Some(node_handle) = self.map.get(&PtrKey::new(key)) {
396 return Some(EntryHandle::new(node_handle.clone()));
397 }
398 None
399 }
400
401 /// Moves the entry associated with the given handle to the tail of the
402 /// LinkedHashMap's iteration order (making it the most recently used).
403 ///
404 /// If the entry is already at the tail of the iteration order, this
405 /// operation has no effect. This method works regardless of whether the
406 /// map uses InsertionOrder or AccessOrder.
407 ///
408 /// Returns `true` if the entry was successfully moved to the tail (or was
409 /// already at the tail), and `false` if the handle is invalid.
410 ///
411 /// This operation completes in O(1) time.
412 ///
413 /// # Examples
414 /// ```
415 /// use deepmesa_collections::LinkedHashMap;
416 /// use deepmesa_collections::lhmap::Order;
417 ///
418 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
419 /// lhm.put(1, "a");
420 /// lhm.put(2, "b");
421 /// lhm.put(3, "c");
422 ///
423 /// if let Some(handle) = lhm.entry_handle(&1) {
424 /// assert!(lhm.make_tail(handle));
425 ///
426 /// // Now key 1 will be the last in iteration order
427 /// let keys: Vec<_> = lhm.keys().copied().collect();
428 /// assert_eq!(keys, vec![2, 3, 1]);
429 /// }
430 /// ```
431 pub fn make_tail(&mut self, eh: EntryHandle<K, V>) -> bool {
432 self.ll.make_tail(&eh.node_handle)
433 }
434
435 /// Moves the entry associated with the given handle to the head of the
436 /// LinkedHashMap's iteration order (making it the least recently used).
437 ///
438 /// If the entry is already at the head of the iteration order, this
439 /// operation has no effect. This method works regardless of whether the
440 /// map uses InsertionOrder or AccessOrder.
441 ///
442 /// Returns `true` if the entry was successfully moved to the head (or was
443 /// already at the head), and `false` if the handle is invalid.
444 ///
445 /// This operation completes in O(1) time.
446 ///
447 /// # Examples
448 /// ```
449 /// use deepmesa_collections::LinkedHashMap;
450 /// use deepmesa_collections::lhmap::Order;
451 ///
452 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
453 /// lhm.put(1, "a");
454 /// lhm.put(2, "b");
455 /// lhm.put(3, "c");
456 ///
457 /// if let Some(handle) = lhm.entry_handle(&3) {
458 /// assert!(lhm.make_head(handle));
459 ///
460 /// // Now key 3 will be the first in iteration order
461 /// let keys: Vec<_> = lhm.keys().copied().collect();
462 /// assert_eq!(keys, vec![3, 1, 2]);
463 /// }
464 /// ```
465 pub fn make_head(&mut self, eh: EntryHandle<K, V>) -> bool {
466 self.ll.make_head(&eh.node_handle)
467 }
468
469 /// Returns a reference to the key-value pair associated with the given EntryHandle.
470 ///
471 /// This method provides O(1) access to an entry using its handle, without affecting
472 /// the iteration order (unlike [`get()`](#method.get) which may move accessed entries
473 /// to the tail in AccessOrder mode).
474 ///
475 /// Returns `Some((key, value))` if the handle is valid, or `None` if the handle
476 /// is invalid (e.g., the entry was removed from the map).
477 ///
478 /// This operation completes in O(1) time.
479 ///
480 /// # Examples
481 /// ```
482 /// use deepmesa_collections::LinkedHashMap;
483 /// use deepmesa_collections::lhmap::Order;
484 ///
485 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
486 /// lhm.put(1, "a");
487 /// lhm.put(2, "b");
488 /// lhm.put(3, "c");
489 ///
490 /// if let Some(handle) = lhm.entry_handle(&2) {
491 /// // Get the entry without affecting iteration order
492 /// assert_eq!(lhm.get_entry(&handle), Some((&2, &"b")));
493 ///
494 /// // Verify order is unchanged
495 /// let keys: Vec<_> = lhm.keys().copied().collect();
496 /// assert_eq!(keys, vec![1, 2, 3]);
497 /// }
498 ///
499 /// // Invalid handle returns None
500 /// let invalid_handle = deepmesa_collections::lhmap::EntryHandle::default();
501 /// assert_eq!(lhm.get_entry(&invalid_handle), None);
502 /// ```
503 pub fn get_entry(&self, handle: &EntryHandle<K, V>) -> Option<(&K, &V)> {
504 if let Some(entry) = handle.node_handle.val(&self.ll) {
505 Some((&entry.key, &entry.val))
506 } else {
507 None
508 }
509 }
510
511 /// Returns a reference to the key associated with the given EntryHandle.
512 ///
513 /// This method provides O(1) access to just the key of an entry using its handle,
514 /// without affecting the iteration order. This is useful when you only need the key
515 /// and want to avoid destructuring the result of [`get_entry()`](#method.get_entry).
516 ///
517 /// Returns `Some(key)` if the handle is valid, or `None` if the handle
518 /// is invalid (e.g., the entry was removed from the map).
519 ///
520 /// This operation completes in O(1) time.
521 ///
522 /// # Examples
523 /// ```
524 /// use deepmesa_collections::LinkedHashMap;
525 /// use deepmesa_collections::lhmap::Order;
526 ///
527 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
528 /// lhm.put(1, "a");
529 /// lhm.put(2, "b");
530 /// lhm.put(3, "c");
531 ///
532 /// if let Some(handle) = lhm.entry_handle(&2) {
533 /// // Get just the key without affecting iteration order
534 /// assert_eq!(lhm.get_key(&handle), Some(&2));
535 ///
536 /// // Verify order is unchanged
537 /// let keys: Vec<_> = lhm.keys().copied().collect();
538 /// assert_eq!(keys, vec![1, 2, 3]);
539 /// }
540 ///
541 /// // Invalid handle returns None
542 /// let invalid_handle = deepmesa_collections::lhmap::EntryHandle::default();
543 /// assert_eq!(lhm.get_key(&invalid_handle), None);
544 /// ```
545 pub fn get_key(&self, handle: &EntryHandle<K, V>) -> Option<&K> {
546 handle.node_handle.val(&self.ll).map(|entry| &entry.key)
547 }
548
549 /// Returns a reference to the value associated with the given EntryHandle.
550 ///
551 /// This method provides O(1) access to just the value of an entry using its handle,
552 /// without affecting the iteration order. This is useful when you only need the value
553 /// and want to avoid destructuring the result of [`get_entry()`](#method.get_entry).
554 ///
555 /// Returns `Some(value)` if the handle is valid, or `None` if the handle
556 /// is invalid (e.g., the entry was removed from the map).
557 ///
558 /// This operation completes in O(1) time.
559 ///
560 /// # Examples
561 /// ```
562 /// use deepmesa_collections::LinkedHashMap;
563 /// use deepmesa_collections::lhmap::Order;
564 ///
565 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
566 /// lhm.put(1, "a");
567 /// lhm.put(2, "b");
568 /// lhm.put(3, "c");
569 ///
570 /// if let Some(handle) = lhm.entry_handle(&2) {
571 /// // Get just the value without affecting iteration order
572 /// assert_eq!(lhm.get_value(&handle), Some(&"b"));
573 ///
574 /// // Verify order is unchanged
575 /// let keys: Vec<_> = lhm.keys().copied().collect();
576 /// assert_eq!(keys, vec![1, 2, 3]);
577 /// }
578 ///
579 /// // Invalid handle returns None
580 /// let invalid_handle = deepmesa_collections::lhmap::EntryHandle::default();
581 /// assert_eq!(lhm.get_value(&invalid_handle), None);
582 /// ```
583 pub fn get_value(&self, handle: &EntryHandle<K, V>) -> Option<&V> {
584 handle.node_handle.val(&self.ll).map(|entry| &entry.val)
585 }
586
587 /// Returns a mutable reference to the value associated with the given EntryHandle.
588 ///
589 /// This method provides O(1) mutable access to the value of an entry using its handle,
590 /// without affecting the iteration order. This allows you to modify the value in-place
591 /// while preserving the entry's position in the map.
592 ///
593 /// Returns `Some(value)` if the handle is valid, or `None` if the handle
594 /// is invalid (e.g., the entry was removed from the map).
595 ///
596 /// This operation completes in O(1) time.
597 ///
598 /// # Examples
599 /// ```
600 /// use deepmesa_collections::LinkedHashMap;
601 /// use deepmesa_collections::lhmap::Order;
602 ///
603 /// let mut lhm = LinkedHashMap::<u16, String>::new(10, Order::InsertionOrder, None);
604 /// lhm.put(1, "a".to_string());
605 /// lhm.put(2, "b".to_string());
606 /// lhm.put(3, "c".to_string());
607 ///
608 /// if let Some(handle) = lhm.entry_handle(&2) {
609 /// // Mutate the value without affecting iteration order
610 /// if let Some(value) = lhm.get_value_mut(&handle) {
611 /// value.push_str("_modified");
612 /// }
613 ///
614 /// // Verify the change
615 /// assert_eq!(lhm.get_value(&handle), Some(&"b_modified".to_string()));
616 ///
617 /// // Verify order is unchanged
618 /// let keys: Vec<_> = lhm.keys().copied().collect();
619 /// assert_eq!(keys, vec![1, 2, 3]);
620 /// }
621 ///
622 /// // Invalid handle returns None
623 /// let invalid_handle = deepmesa_collections::lhmap::EntryHandle::default();
624 /// assert_eq!(lhm.get_value_mut(&invalid_handle), None);
625 /// ```
626 pub fn get_value_mut(&mut self, handle: &EntryHandle<K, V>) -> Option<&mut V> {
627 handle.node_handle.val_mut(&mut self.ll).map(|entry| &mut entry.val)
628 }
629
630 /// Removes and returns the head (oldest) entry from the LinkedHashMap.
631 ///
632 /// The head entry is the least recently inserted or accessed entry depending
633 /// on the map's order mode. This is the same entry that would be removed by
634 /// the eviction policy.
635 ///
636 /// Returns `Some((key, value))` if an entry was removed, or `None` if the
637 /// map is empty.
638 ///
639 /// This operation completes in O(1) time.
640 ///
641 /// # Examples
642 /// ```
643 /// use deepmesa_collections::LinkedHashMap;
644 /// use deepmesa_collections::lhmap::Order;
645 ///
646 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
647 /// lhm.put(1, "a");
648 /// lhm.put(2, "b");
649 /// lhm.put(3, "c");
650 ///
651 /// // Remove the head (oldest entry)
652 /// assert_eq!(lhm.remove_head(), Some((1, "a")));
653 /// assert_eq!(lhm.remove_head(), Some((2, "b")));
654 /// assert_eq!(lhm.remove_head(), Some((3, "c")));
655 /// assert_eq!(lhm.remove_head(), None);
656 /// ```
657 /// Returns a reference to the head (oldest) entry in the LinkedHashMap.
658 ///
659 /// The head entry is the least recently inserted or accessed entry depending
660 /// on the map's order mode. This is the entry that would be removed by the
661 /// eviction policy.
662 ///
663 /// Returns `Some((&key, &value))` if the map is not empty, or `None` if the
664 /// map is empty.
665 ///
666 /// This operation completes in O(1) time and does not modify the map.
667 ///
668 /// Returns a reference to the entry at the head of the LinkedHashMap.
669 ///
670 /// This method does not change the access order and works the same
671 /// regardless of whether the map uses InsertionOrder or AccessOrder.
672 /// Unlike insertion operations, this method is purely a read operation
673 /// and will not affect the ordering of entries.
674 ///
675 /// # Examples
676 /// ```
677 /// use deepmesa_collections::LinkedHashMap;
678 /// use deepmesa_collections::lhmap::Order;
679 ///
680 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
681 /// assert_eq!(lhm.head(), None);
682 ///
683 /// lhm.put(1, "a");
684 /// lhm.put(2, "b");
685 /// lhm.put(3, "c");
686 ///
687 /// // Head is the oldest entry
688 /// assert_eq!(lhm.head(), Some((&1, &"a")));
689 /// ```
690 pub fn head(&self) -> Option<(&K, &V)> {
691 if let Some(entry) = self.ll.head() {
692 Some((&entry.key, &entry.val))
693 } else {
694 None
695 }
696 }
697
698 pub fn remove_head(&mut self) -> Option<(K, V)> {
699 if let Some(entry) = self.ll.pop_head() {
700 self.map.remove(&PtrKey::new(&entry.key));
701 Some((entry.key, entry.val))
702 } else {
703 None
704 }
705 }
706
707 /// Removes and returns the tail (newest) entry from the LinkedHashMap.
708 ///
709 /// The tail entry is the most recently inserted or accessed entry depending
710 /// on the map's order mode. This is the opposite of the entry that would be
711 /// removed by the eviction policy.
712 ///
713 /// Returns `Some((key, value))` if an entry was removed, or `None` if the
714 /// map is empty.
715 ///
716 /// This operation completes in O(1) time.
717 ///
718 /// # Examples
719 /// ```
720 /// use deepmesa_collections::LinkedHashMap;
721 /// use deepmesa_collections::lhmap::Order;
722 ///
723 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
724 /// lhm.put(1, "a");
725 /// lhm.put(2, "b");
726 /// lhm.put(3, "c");
727 ///
728 /// // Remove the tail (newest entry)
729 /// assert_eq!(lhm.remove_tail(), Some((3, "c")));
730 /// assert_eq!(lhm.remove_tail(), Some((2, "b")));
731 /// assert_eq!(lhm.remove_tail(), Some((1, "a")));
732 /// assert_eq!(lhm.remove_tail(), None);
733 /// ```
734 /// Returns a reference to the tail (newest) entry in the LinkedHashMap.
735 ///
736 /// The tail entry is the most recently inserted or accessed entry depending
737 /// on the map's order mode. This is the opposite of the entry that would be
738 /// removed by the eviction policy.
739 ///
740 /// Returns `Some((&key, &value))` if the map is not empty, or `None` if the
741 /// map is empty.
742 ///
743 /// This operation completes in O(1) time and does not modify the map.
744 ///
745 /// Returns a reference to the entry at the tail of the LinkedHashMap.
746 ///
747 /// This method does not change the access order and works the same
748 /// regardless of whether the map uses InsertionOrder or AccessOrder.
749 /// Unlike insertion operations, this method is purely a read operation
750 /// and will not affect the ordering of entries.
751 ///
752 /// # Examples
753 /// ```
754 /// use deepmesa_collections::LinkedHashMap;
755 /// use deepmesa_collections::lhmap::Order;
756 ///
757 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
758 /// assert_eq!(lhm.tail(), None);
759 ///
760 /// lhm.put(1, "a");
761 /// lhm.put(2, "b");
762 /// lhm.put(3, "c");
763 ///
764 /// // Tail is the newest entry
765 /// assert_eq!(lhm.tail(), Some((&3, &"c")));
766 /// ```
767 pub fn tail(&self) -> Option<(&K, &V)> {
768 if let Some(entry) = self.ll.tail() {
769 Some((&entry.key, &entry.val))
770 } else {
771 None
772 }
773 }
774
775 pub fn remove_tail(&mut self) -> Option<(K, V)> {
776 if let Some(entry) = self.ll.pop_tail() {
777 self.map.remove(&PtrKey::new(&entry.key));
778 Some((entry.key, entry.val))
779 } else {
780 None
781 }
782 }
783
784 /// Returns a reference to the value corresponding to the key. If
785 /// the Map was created with AccessOrder then the key accessed is
786 /// moved to the tail of the underlying linked list (most
787 /// recently used).
788 ///
789 /// If the key is not present then this method returns None and
790 /// the order is unaffected.
791 ///
792 /// # Examples
793 ///
794 /// ```
795 /// use deepmesa_collections::LinkedHashMap;
796 /// use deepmesa_collections::lhmap::Order;
797 ///
798 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
799 /// lhm.insert(1, "a");
800 /// lhm.insert(2, "b");
801 ///
802 /// let mut iter = lhm.iter();
803 /// assert_eq!(iter.next(), Some((&1, &"a")));
804 /// assert_eq!(iter.next(), Some((&2, &"b")));
805 ///
806 /// assert_eq!(lhm.get(&1), Some(&"a"));
807 /// assert_eq!(lhm.get(&3), None);
808 ///
809 /// let mut iter = lhm.iter();
810 /// assert_eq!(iter.next(), Some((&2, &"b")));
811 /// assert_eq!(iter.next(), Some((&1, &"a")));
812 /// assert_eq!(iter.next(), None);
813 ///
814 /// ```
815 pub fn get(&mut self, key: &K) -> Option<&V> {
816 if let Some(llnode) = self.map.get(&PtrKey::new(key)) {
817 if self.order == Order::AccessOrder {
818 if !self.ll.make_tail(llnode) {
819 panic!("failed to make tail!");
820 }
821 }
822
823 match llnode.val(&self.ll) {
824 None => panic!("List does not doesn't contain expected value!"),
825 Some(entry) => {
826 return Some(&entry.val);
827 }
828 }
829 }
830 None
831 }
832
833 /// Returns the key-value pair corresponding to the supplied key.
834 /// the Map was created with AccessOrder then the key accessed is
835 /// moved to the tail of the underlying linked list (most
836 /// recently accessed).
837 ///
838 /// If the key is not present then this method returns None and
839 /// the order is unaffected.
840 ///
841 /// # Examples
842 /// ```
843 /// use deepmesa_collections::LinkedHashMap;
844 /// use deepmesa_collections::lhmap::Order;
845 ///
846 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
847 /// lhm.insert(1, "a");
848 /// lhm.insert(2, "b");
849 ///
850 /// let mut iter = lhm.iter();
851 /// assert_eq!(iter.next(), Some((&1, &"a")));
852 /// assert_eq!(iter.next(), Some((&2, &"b")));
853 ///
854 /// assert_eq!(lhm.get_key_value(&1), Some((&1, &"a")));
855 /// assert_eq!(lhm.get(&3), None);
856 ///
857 /// let mut iter = lhm.iter();
858 /// assert_eq!(iter.next(), Some((&2, &"b")));
859 /// assert_eq!(iter.next(), Some((&1, &"a")));
860 /// assert_eq!(iter.next(), None);
861 ///
862 /// ```
863 pub fn get_key_value(&mut self, key: &K) -> Option<(&K, &V)> {
864 if let Some(llnode) = self.map.get(&PtrKey::new(key)) {
865 if self.order == Order::AccessOrder {
866 if !self.ll.make_tail(llnode) {
867 panic!("failed to make tail!");
868 }
869 }
870
871 match llnode.val(&self.ll) {
872 None => panic!("List does not doesn't contain expected value!"),
873 Some(entry) => {
874 return Some((&entry.key, &entry.val));
875 }
876 }
877 }
878 None
879 }
880
881 /// Returns a mutable reference to the value corresponding to the key. If
882 /// the Map was created with AccessOrder then the key accessed is
883 /// moved to the tail of the underlying linked list (most
884 /// recently used).
885 ///
886 /// If the key is not present then this method returns None and
887 /// the order is unaffected.
888 ///
889 /// # Examples
890 ///
891 /// ```
892 /// use deepmesa_collections::LinkedHashMap;
893 /// use deepmesa_collections::lhmap::Order;
894 ///
895 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
896 /// lhm.insert(1, "a");
897 /// lhm.insert(2, "b");
898 ///
899 /// let mut iter = lhm.iter();
900 /// assert_eq!(iter.next(), Some((&1, &"a")));
901 /// assert_eq!(iter.next(), Some((&2, &"b")));
902 ///
903 /// if let Some(val) = lhm.get_mut(&1) {
904 /// *val = "d";
905 /// }
906 ///
907 /// let mut iter = lhm.iter();
908 /// assert_eq!(iter.next(), Some((&2, &"b")));
909 /// assert_eq!(iter.next(), Some((&1, &"d")));
910 /// assert_eq!(iter.next(), None);
911 ///
912 /// ```
913 pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
914 if let Some(llnode) = self.map.get(&PtrKey::new(key)) {
915 if self.order == Order::AccessOrder {
916 if !self.ll.make_tail(llnode) {
917 panic!("failed to make tail!");
918 }
919 }
920
921 match llnode.val_mut(&mut self.ll) {
922 None => panic!("List does not doesn't contain expected value!"),
923 Some(entry) => {
924 return Some(&mut entry.val);
925 }
926 }
927 }
928 None
929 }
930
931 /// Removes a key from the map, returning the value at the key if
932 /// the key was previously in the map. If the key was not present
933 /// then this method returns None. The iteration order is not
934 /// affected by this method except to remove the specified key
935 /// from the underlying linked list.
936 ///
937 /// # Examples
938 ///
939 /// ```
940 /// use deepmesa_collections::LinkedHashMap;
941 /// use deepmesa_collections::lhmap::Order;
942 ///
943 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
944 /// lhm.insert(1, "a");
945 /// assert_eq!(lhm.remove(&1), Some("a"));
946 /// assert_eq!(lhm.remove(&1), None);
947 /// ```
948 pub fn remove(&mut self, key: &K) -> Option<V> {
949 if let Some(llnode) = self.map.remove(&PtrKey::new(key)) {
950 match self.ll.pop_node(&llnode) {
951 None => panic!("List doesn't contain expected value!"),
952 Some(entry) => return Some(entry.val),
953 }
954 }
955
956 None
957 }
958
959 /// Removes a key from the map, returning the key value pair at
960 /// the key if the key was previously in the map. If the key was
961 /// not present then this method returns None. The iteration order
962 /// is not affected by this method except to remove the specified
963 /// key from the underlying linked list.
964 ///
965 /// # Examples
966 ///
967 /// ```
968 /// use deepmesa_collections::LinkedHashMap;
969 /// use deepmesa_collections::lhmap::Order;
970 ///
971 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
972 /// lhm.insert(1, "a");
973 /// assert_eq!(lhm.remove_entry(&1), Some((1, "a")));
974 /// assert_eq!(lhm.remove(&1), None);
975 /// ```
976 pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)> {
977 if let Some(llnode) = self.map.remove(&PtrKey::new(key)) {
978 match self.ll.pop_node(&llnode) {
979 None => panic!("List doesn't contain expected value!"),
980 Some(entry) => return Some((entry.key, entry.val)),
981 }
982 }
983
984 None
985 }
986
987 /// Inserts a key-value pair into the map. Unlike the insert
988 /// method this does not return the old value previously stored.
989 /// The new value inserted is placed at the tail of the underlying
990 /// linked list (most recently used).
991 ///
992 /// #Examples
993 /// ```
994 /// use deepmesa_collections::LinkedHashMap;
995 /// use deepmesa_collections::lhmap::Order;
996 ///
997 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
998 /// lhm.put(1, "a");
999 /// assert_eq!(lhm.is_empty(), false);
1000 /// ```
1001 pub fn put(&mut self, k: K, v: V) {
1002 match self.map.get(&PtrKey::new(&k)) {
1003 Some(llnode) => match llnode.val_mut(&mut self.ll) {
1004 None => panic!("Value not found in LL"),
1005 Some(entry) => {
1006 (*entry).val = v;
1007 if !self.ll.make_tail(llnode) {
1008 panic!("failed to make tail!");
1009 }
1010 }
1011 },
1012 None => {
1013 let ll_node = self.ll.push_tail(Entry::new(k, v));
1014
1015 match self.ll.node(&ll_node) {
1016 None => panic!("Value not found in LL"),
1017 Some(entry_ref) => unsafe {
1018 let key_ptr = entry_ref.key_ptr();
1019 self.map.insert(PtrKey::from_ptr(key_ptr), ll_node);
1020 },
1021 }
1022 }
1023 }
1024
1025 self.evict_eldest();
1026 }
1027
1028 /// Inserts a key-value pair into the map and returns the old
1029 /// value (if any). If a value was not present for this key then
1030 /// this method returns None. The new value inserted is placed at
1031 /// the tail of the underlying linked list (most recently used).
1032 ///
1033 /// The key is not updated and only the value corresponding to the
1034 /// key is updated.
1035 ///
1036 /// #Examples
1037 /// ```
1038 /// use deepmesa_collections::LinkedHashMap;
1039 /// use deepmesa_collections::lhmap::Order;
1040 ///
1041 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
1042 /// assert_eq!(lhm.insert(1, "a"), None);
1043 /// assert_eq!(lhm.is_empty(), false);
1044 ///
1045 /// lhm.insert(2, "b");
1046 /// assert_eq!(lhm.insert(2, "c"), Some("b"));
1047 /// ```
1048 pub fn insert(&mut self, k: K, v: V) -> Option<V> {
1049 let mut retval: Option<V> = None;
1050
1051 match self.map.get(&PtrKey::new(&k)) {
1052 None => {
1053 let ll_node = self.ll.push_tail(Entry::new(k, v));
1054
1055 match self.ll.node(&ll_node) {
1056 None => panic!("Value not found in LL"),
1057 Some(entry_ref) => unsafe {
1058 let key_ptr = entry_ref.key_ptr();
1059 self.map.insert(PtrKey::from_ptr(key_ptr), ll_node);
1060 },
1061 }
1062 }
1063 Some(llnode) => match llnode.val_mut(&mut self.ll) {
1064 None => panic!("value not found in linkedlist"),
1065 Some(entry) => {
1066 retval = Some(std::mem::replace(&mut (*entry).val, v));
1067 if !self.ll.make_tail(llnode) {
1068 panic!("failed to make tail!");
1069 }
1070 }
1071 },
1072 }
1073
1074 self.evict_eldest();
1075 return retval;
1076 }
1077
1078 /// An Iterator that vists all key value pairs in a predictable
1079 /// order.
1080 ///
1081 /// Iteration over the map requires time proportional to the
1082 /// length of the map (*O*(*len*)) regardless of the capacity
1083 /// because it iterates over the elements of the underlying linked
1084 /// list. If the map is constructed with [`InsertionOrder`](Order)
1085 /// then the iteration order is from oldest entry inserted to the
1086 /// newest entry inserted. If the map is constructed with
1087 /// [`AccessOrder`](Order) then the iteration order is from oldest
1088 /// entry accessed to the newest entry accessed.
1089 ///
1090 /// The iterator element type is (&'a K, &'a V).
1091 ///
1092 /// # Examples
1093 /// ```
1094 /// use deepmesa_collections::LinkedHashMap;
1095 /// use deepmesa_collections::lhmap::Order;
1096 ///
1097 /// // Construct a map in InsertionOrder
1098 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1099 /// lhm.put(1, "a");
1100 /// lhm.put(2, "b");
1101 ///
1102 /// lhm.get(&1);
1103 ///
1104 /// let mut iter = lhm.iter();
1105 /// assert_eq!(iter.next(), Some((&1, &"a")));
1106 /// assert_eq!(iter.next(), Some((&2, &"b")));
1107 ///
1108 /// // Construct a map in AccessOrder
1109 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
1110 /// lhm.put(1, "a");
1111 /// lhm.put(2, "b");
1112 ///
1113 /// lhm.get(&1);
1114 ///
1115 /// let mut iter = lhm.iter();
1116 /// assert_eq!(iter.next(), Some((&2, &"b")));
1117 /// assert_eq!(iter.next(), Some((&1, &"a")));
1118 /// ```
1119 pub fn iter(&self) -> Iter<'_, K, V> {
1120 return Iter::new(self);
1121 }
1122
1123 /// An Iterator that vists all key value pairs in a predictable
1124 /// order with mutable references to the values.
1125 ///
1126 /// Iteration over the map requires time proportional to the
1127 /// length of the map (*O*(*len*)) regardless of the capacity
1128 /// because it iterates over the elements of the underlying linked
1129 /// list. If the map is constructed with [`InsertionOrder`](Order)
1130 /// then the iteration order is from oldest entry inserted to the
1131 /// newest entry inserted. If the map is constructed with
1132 /// [`AccessOrder`](Order) then the iteration order is from oldest
1133 /// entry accessed to the newest entry accessed
1134 ///
1135 /// The iterator element type is (&'a K, &'a mut V).
1136 ///
1137 /// # Examples
1138 /// ```
1139 /// use deepmesa_collections::LinkedHashMap;
1140 /// use deepmesa_collections::lhmap::Order;
1141 ///
1142 /// // Construct a map in InsertionOrder
1143 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1144 /// lhm.put(1, "a");
1145 /// lhm.put(2, "b");
1146 ///
1147 /// lhm.get(&1);
1148 ///
1149 /// for (_, val) in lhm.iter_mut() {
1150 /// *val = "d";
1151 /// }
1152 ///
1153 /// assert_eq!(lhm.get(&1), Some(&"d"));
1154 /// assert_eq!(lhm.get(&2), Some(&"d"));
1155 ///
1156 /// ```
1157 pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
1158 return IterMut::new(self);
1159 }
1160
1161 /// An Iterator that vists all keys in a predictable order.
1162 ///
1163 /// Iteration over the map requires time proportional to the
1164 /// length of the map (*O*(*len*)) regardless of the capacity
1165 /// because it iterates over the elements of the underlying linked
1166 /// list. If the map is constructed with [`InsertionOrder`](Order)
1167 /// then the iteration order is from oldest entry inserted to the
1168 /// newest entry inserted. If the map is constructed with
1169 /// [`AccessOrder`](Order) then the iteration order is from oldest
1170 /// entry accessed to the newest entry accessed.
1171 ///
1172 /// The iterator element type is &'a K.
1173 ///
1174 /// # Examples
1175 /// ```
1176 /// use deepmesa_collections::LinkedHashMap;
1177 /// use deepmesa_collections::lhmap::Order;
1178 ///
1179 /// // Construct a map in InsertionOrder
1180 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1181 /// lhm.put(1, "a");
1182 /// lhm.put(2, "b");
1183 ///
1184 /// lhm.get(&1);
1185 ///
1186 /// let mut iter = lhm.keys();
1187 /// assert_eq!(iter.next(), Some((&1)));
1188 /// assert_eq!(iter.next(), Some((&2)));
1189 ///
1190 /// // Construct a map in AccessOrder
1191 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
1192 /// lhm.put(1, "a");
1193 /// lhm.put(2, "b");
1194 ///
1195 /// lhm.get(&1);
1196 ///
1197 /// let mut iter = lhm.keys();
1198 /// assert_eq!(iter.next(), Some((&2)));
1199 /// assert_eq!(iter.next(), Some((&1)));
1200 /// ```
1201 pub fn keys(&self) -> Keys<'_, K, V> {
1202 return Keys::new(self);
1203 }
1204
1205 /// An Iterator that vists all values in a predictable order.
1206 ///
1207 /// Iteration over the map requires time proportional to the
1208 /// length of the map (*O*(*len*)) regardless of the capacity
1209 /// because it iterates over the elements of the underlying linked
1210 /// list. If the map is constructed with [`InsertionOrder`](Order)
1211 /// then the iteration order is from oldest entry inserted to the
1212 /// newest entry inserted. If the map is constructed with
1213 /// [`AccessOrder`](Order) then the iteration order is from oldest
1214 /// entry accessed to the newest entry accessed.
1215 ///
1216 /// The iterator element type is &'a V.
1217 ///
1218 /// # Examples
1219 /// ```
1220 /// use deepmesa_collections::LinkedHashMap;
1221 /// use deepmesa_collections::lhmap::Order;
1222
1223 ///
1224 /// // Construct a map in InsertionOrder
1225 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1226 /// lhm.put(1, "a");
1227 /// lhm.put(2, "b");
1228 ///
1229 /// lhm.get(&1);
1230 ///
1231 /// let mut iter = lhm.values();
1232 /// assert_eq!(iter.next(), Some((&"a")));
1233 /// assert_eq!(iter.next(), Some((&"b")));
1234 ///
1235 /// // Construct a map in AccessOrder
1236 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
1237 /// lhm.put(1, "a");
1238 /// lhm.put(2, "b");
1239 ///
1240 /// lhm.get(&1);
1241 ///
1242 /// let mut iter = lhm.values();
1243 /// assert_eq!(iter.next(), Some((&"b")));
1244 /// assert_eq!(iter.next(), Some((&"a")));
1245 /// ```
1246 pub fn values(&self) -> Values<'_, K, V> {
1247 return Values::new(self);
1248 }
1249
1250 /// An Iterator that vists all values in a predictable order with
1251 /// mutable references to the values.
1252 ///
1253 /// Iteration over the map requires time proportional to the
1254 /// length of the map (*O*(*len*)) regardless of the capacity
1255 /// because it iterates over the elements of the underlying linked
1256 /// list. If the map is constructed with [`InsertionOrder`](Order)
1257 /// then the iteration order is from oldest entry inserted to the
1258 /// newest entry inserted. If the map is constructed with
1259 /// [`AccessOrder`](Order) then the iteration order is from oldest
1260 /// entry accessed to the newest entry accessed.
1261 ///
1262 /// The iterator element type is &'a mut V.
1263 ///
1264 /// # Examples
1265 /// ```
1266 /// use deepmesa_collections::LinkedHashMap;
1267 /// use deepmesa_collections::lhmap::Order;
1268 ///
1269 /// // Construct a map in InsertionOrder
1270 /// let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1271 /// lhm.put(1, "a");
1272 /// lhm.put(2, "b");
1273 ///
1274 /// lhm.get(&1);
1275 ///
1276 /// for val in lhm.values_mut() {
1277 /// *val = "d";
1278 /// }
1279 ///
1280 /// assert_eq!(lhm.get(&1), Some(&"d"));
1281 /// assert_eq!(lhm.get(&2), Some(&"d"));
1282 ///
1283 /// ```
1284 pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
1285 return ValuesMut::new(self);
1286 }
1287
1288 fn evict_eldest(&mut self) {
1289 if let Some(ee_fn) = self.evict_eldest {
1290 if let Some(entry) = self.ll.head() {
1291 if ee_fn(self.len(), self.cap, entry) {
1292 match self.ll.pop_head() {
1293 None => panic!("pop head unexpectedly returned None"),
1294 Some(entry) => {
1295 self.map.remove(&PtrKey::new(&entry.key));
1296 }
1297 }
1298 }
1299 }
1300 }
1301 }
1302}
1303
1304#[cfg(test)]
1305mod tests {
1306 use super::Order;
1307 use crate::lhmap::entry::Entry;
1308 use crate::lhmap::lhmap::LinkedHashMap;
1309
1310 #[derive(Debug)]
1311 struct ValObject {
1312 int_v: u16,
1313 }
1314
1315 impl ValObject {
1316 fn new(val: u16) -> ValObject {
1317 return ValObject { int_v: val };
1318 }
1319 }
1320
1321 #[test]
1322 fn test_iter() {
1323 let mut lhm: LinkedHashMap<String, ValObject> =
1324 LinkedHashMap::new(10, Order::AccessOrder, None);
1325
1326 for i in 0u16..10 {
1327 lhm.put(format!("Hello-{}", i), ValObject::new(i));
1328 assert_eq!((i + 1) as usize, lhm.len());
1329 }
1330
1331 lhm.get(&"Hello-3".to_string());
1332
1333 let mut iter = lhm.iter();
1334 while let Some((key, val)) = iter.next() {
1335 println!("Key: {:?}, Val: {:?}", key, val);
1336 }
1337
1338 println!("Now using IntoIterator!");
1339
1340 for (key, val) in lhm.iter() {
1341 println!("Key: {:?}, Val: {:?}", key, val);
1342 }
1343
1344 println!("Now using Keys!");
1345
1346 let mut keys = lhm.keys();
1347 while let Some(key) = keys.next() {
1348 println!("Key: {:?}", key);
1349 }
1350
1351 println!("Now using Values!");
1352
1353 let mut values = lhm.values();
1354 while let Some(val) = values.next() {
1355 println!("Value: {:?}", val);
1356 }
1357 }
1358
1359 #[test]
1360 fn test_put_get_remove() {
1361 let mut lhm: LinkedHashMap<String, ValObject> =
1362 LinkedHashMap::new(10, Order::AccessOrder, None);
1363
1364 for i in 0u16..10 {
1365 lhm.put(format!("Hello-{}", i), ValObject::new(i));
1366 assert_eq!((i + 1) as usize, lhm.len());
1367 }
1368
1369 for i in 0u16..10 {
1370 match lhm.get(&format!("Hello-{}", i)) {
1371 None => {
1372 assert!(false, "Unexpected None for Key Hello-{}", i);
1373 assert_eq!(10, lhm.len());
1374 }
1375 Some(val_o) => {
1376 assert_eq!(val_o.int_v, i);
1377 }
1378 }
1379 }
1380
1381 for i in 0u16..10 {
1382 match lhm.remove(&format!("Hello-{}", i)) {
1383 None => {
1384 assert!(false, "Unexpected None for removed Key Hello-{}", i);
1385 }
1386 Some(val_o) => {
1387 assert_eq!(val_o.int_v, i);
1388 }
1389 }
1390
1391 match lhm.get(&format!("Hello-{}", i)) {
1392 None => {
1393 assert!(true);
1394 }
1395 Some(val_o) => {
1396 assert!(false, "Unexpected Some with val: {}", val_o.int_v);
1397 }
1398 }
1399 }
1400 }
1401
1402 #[test]
1403 fn test_put_overwrite() {
1404 let mut lhm: LinkedHashMap<String, ValObject> =
1405 LinkedHashMap::new(10, Order::AccessOrder, None);
1406 lhm.put("Hello-0".to_string(), ValObject::new(0));
1407 assert_eq!(lhm.len(), 1);
1408
1409 match lhm.get(&"Hello-0".to_string()) {
1410 None => {
1411 assert!(false, "Unexpected None for Key Hello-0");
1412 }
1413 Some(val_o) => {
1414 assert_eq!(val_o.int_v, 0);
1415 assert_eq!(lhm.len(), 1);
1416 }
1417 }
1418
1419 lhm.put("Hello-0".to_string(), ValObject::new(10));
1420 match lhm.get(&"Hello-0".to_string()) {
1421 None => {
1422 assert!(false, "Unexpected None for Key Hello-0");
1423 }
1424 Some(val_o) => {
1425 assert_eq!(val_o.int_v, 10);
1426 assert_eq!(lhm.len(), 1);
1427 }
1428 }
1429 }
1430
1431 fn evict_fn<K, V>(len: usize, capacity: usize, _e: &Entry<K, V>) -> bool {
1432 if len > capacity {
1433 return true;
1434 }
1435 return false;
1436 }
1437
1438 #[test]
1439 fn test_eviction() {
1440 let mut lhm: LinkedHashMap<String, ValObject> =
1441 LinkedHashMap::new(10, Order::AccessOrder, Some(evict_fn));
1442
1443 for i in 0u16..20 {
1444 lhm.put(format!("Hello-{}", i), ValObject::new(i));
1445 if i >= 10 {
1446 assert_eq!(10, lhm.len());
1447 } else {
1448 assert_eq!((i + 1) as usize, lhm.len());
1449 }
1450 }
1451 }
1452
1453 #[test]
1454 fn test_foo() {
1455 use crate::lhmap::entry::Entry;
1456 pub fn evict<K, V>(len: usize, capacity: usize, _e: &Entry<K, V>) -> bool {
1457 if len > capacity {
1458 return true;
1459 }
1460 return false;
1461 }
1462
1463 use crate::lhmap::entry::Order;
1464 use crate::lhmap::lhmap::LinkedHashMap;
1465
1466 let mut lhm = LinkedHashMap::<u16, &str>::new(2, Order::AccessOrder, Some(evict));
1467 lhm.put(1, "a");
1468 lhm.put(2, "b");
1469 lhm.put(3, "c");
1470
1471 assert_eq!(lhm.get(&2), Some(&"b"));
1472 lhm.put(4, "d");
1473 assert_eq!(lhm.get(&1), None);
1474
1475 // let mut lhm = LinkedHashMap::<&str, u16>::with_capacity(10);
1476 // lhm.put("a", 1);
1477 // lhm.put("b", 2);
1478 // lhm.put("c", 3);
1479 // lhm.put("d", 4);
1480
1481 // let mut iter = lhm.iter();
1482 // println!("{:?}", iter.next());
1483 // println!("{:?}", iter.next());
1484 // println!("{:?}", iter.next());
1485 // println!("{:?}", iter.next());
1486 // println!("{:?}", iter.next());
1487 // println!("{:?}", iter.next());
1488 // println!("Now in reverse!");
1489 // iter = iter.reverse();
1490 // println!("{:?}", iter.next());
1491 // println!("{:?}", iter.next());
1492
1493 // println!("Now in reverse!");
1494
1495 // //assert_eq!(lhm.get(&"a"), Some(&1));
1496 // let mut iter = lhm.iter().reverse();
1497 // println!("{:?}", iter.next());
1498 // println!("{:?}", iter.next());
1499 // println!("{:?}", iter.next());
1500 }
1501
1502 #[test]
1503 fn test_entry_handle_basic() {
1504 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1505 lhm.put(1, "a");
1506 lhm.put(2, "b");
1507 lhm.put(3, "c");
1508
1509 // Test getting valid handle
1510 let handle1 = lhm.entry_handle(&1);
1511 assert!(handle1.is_some());
1512
1513 // Test getting invalid handle
1514 let handle_invalid = lhm.entry_handle(&99);
1515 assert!(handle_invalid.is_none());
1516 }
1517
1518
1519 #[test]
1520 fn test_entry_handle_make_tail_insertion_order() {
1521 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1522 lhm.put(1, "a");
1523 lhm.put(2, "b");
1524 lhm.put(3, "c");
1525
1526 // Initial order should be 1, 2, 3
1527 let keys: Vec<_> = lhm.keys().copied().collect();
1528 assert_eq!(keys, vec![1, 2, 3]);
1529
1530 // Move key 1 to end
1531 if let Some(handle) = lhm.entry_handle(&1) {
1532 assert!(lhm.make_tail(handle));
1533 }
1534
1535 // Order should now be 2, 3, 1
1536 let keys: Vec<_> = lhm.keys().copied().collect();
1537 assert_eq!(keys, vec![2, 3, 1]);
1538
1539 // Values should remain unchanged (use mutable reference for get)
1540 assert_eq!(lhm.get(&1), Some(&"a"));
1541 assert_eq!(lhm.get(&2), Some(&"b"));
1542 assert_eq!(lhm.get(&3), Some(&"c"));
1543 }
1544
1545 #[test]
1546 fn test_entry_handle_make_tail_access_order() {
1547 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
1548 lhm.put(1, "a");
1549 lhm.put(2, "b");
1550 lhm.put(3, "c");
1551
1552 // Initial order should be 1, 2, 3 (insertion order)
1553 let keys: Vec<_> = lhm.keys().copied().collect();
1554 assert_eq!(keys, vec![1, 2, 3]);
1555
1556 // Move key 1 to end using handle (should work regardless of AccessOrder)
1557 if let Some(handle) = lhm.entry_handle(&1) {
1558 assert!(lhm.make_tail(handle));
1559 }
1560
1561 // Order should now be 2, 3, 1
1562 let keys: Vec<_> = lhm.keys().copied().collect();
1563 assert_eq!(keys, vec![2, 3, 1]);
1564 }
1565
1566 #[test]
1567 fn test_entry_handle_make_tail_already_at_end() {
1568 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1569 lhm.put(1, "a");
1570 lhm.put(2, "b");
1571 lhm.put(3, "c");
1572
1573 // Move key 3 to end first to make it actually at the end
1574 if let Some(handle) = lhm.entry_handle(&3) {
1575 assert!(lhm.make_tail(handle));
1576 }
1577
1578 // Now 3 should be at the end: [1, 2, 3]
1579 let keys: Vec<_> = lhm.keys().copied().collect();
1580 assert_eq!(keys, vec![1, 2, 3]);
1581
1582 // Move key 3 to end again (it's already at the end)
1583 if let Some(handle) = lhm.entry_handle(&3) {
1584 assert!(lhm.make_tail(handle));
1585 }
1586
1587 // Order should remain the same: 1, 2, 3
1588 let keys: Vec<_> = lhm.keys().copied().collect();
1589 assert_eq!(keys, vec![1, 2, 3]);
1590 }
1591
1592 #[test]
1593 fn test_entry_handle_invalid_handle() {
1594 let mut lhm1 = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1595 let mut lhm2 = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1596
1597 lhm1.put(1, "a");
1598 lhm2.put(1, "b");
1599
1600 // Get handle from lhm1
1601 let handle = lhm1.entry_handle(&1).unwrap();
1602
1603 // Remove the entry from lhm1 to invalidate the handle
1604 lhm1.remove(&1);
1605
1606 // Try to use invalid handle - should return false
1607 assert_eq!(lhm1.make_tail(handle), false);
1608 }
1609
1610 #[test]
1611 fn test_entry_handle_multiple_operations() {
1612 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1613 lhm.put(1, "a");
1614 lhm.put(2, "b");
1615 lhm.put(3, "c");
1616 lhm.put(4, "d");
1617
1618 // Initial order: [1, 2, 3, 4]
1619 let keys: Vec<_> = lhm.keys().copied().collect();
1620 assert_eq!(keys, vec![1, 2, 3, 4]);
1621
1622 // Move key 2 to end: [1, 3, 4, 2]
1623 if let Some(handle) = lhm.entry_handle(&2) {
1624 assert!(lhm.make_tail(handle));
1625 }
1626 let keys: Vec<_> = lhm.keys().copied().collect();
1627 assert_eq!(keys, vec![1, 3, 4, 2]);
1628
1629 // Move key 1 to end: [3, 4, 2, 1]
1630 if let Some(handle) = lhm.entry_handle(&1) {
1631 assert!(lhm.make_tail(handle));
1632 }
1633 let keys: Vec<_> = lhm.keys().copied().collect();
1634 assert_eq!(keys, vec![3, 4, 2, 1]);
1635 }
1636
1637 #[test]
1638 fn test_entry_handle_with_access_operations() {
1639 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
1640 lhm.put(1, "a");
1641 lhm.put(2, "b");
1642 lhm.put(3, "c");
1643
1644 // Initial order: [1, 2, 3]
1645 let keys: Vec<_> = lhm.keys().copied().collect();
1646 assert_eq!(keys, vec![1, 2, 3]);
1647
1648 // Access key 1 (should move it to head in AccessOrder, making it last in iteration)
1649 lhm.get(&1);
1650 let keys: Vec<_> = lhm.keys().copied().collect();
1651 assert_eq!(keys, vec![2, 3, 1]); // 1 moved to most recently accessed (end)
1652
1653 // Use handle to move key 2 to end (should move it to head of list, end of iteration)
1654 if let Some(handle) = lhm.entry_handle(&2) {
1655 assert!(lhm.make_tail(handle));
1656 }
1657 let keys: Vec<_> = lhm.keys().copied().collect();
1658 assert_eq!(keys, vec![3, 1, 2]); // 2 moved to end
1659 }
1660
1661 #[test]
1662 fn test_entry_handle_default() {
1663 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1664 lhm.put(1, "a");
1665
1666 // Create a default handle (invalid)
1667 let default_handle = crate::lhmap::entry::EntryHandle::<u16, &str>::default();
1668
1669 // Try to use it - should return false
1670 assert_eq!(lhm.make_tail(default_handle), false);
1671 }
1672
1673 #[test]
1674 fn test_get_entry_basic() {
1675 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1676 lhm.put(1, "a");
1677 lhm.put(2, "b");
1678 lhm.put(3, "c");
1679
1680 // Test getting valid entries
1681 if let Some(handle1) = lhm.entry_handle(&1) {
1682 assert_eq!(lhm.get_entry(&handle1), Some((&1, &"a")));
1683 } else {
1684 panic!("Expected valid handle for key 1");
1685 }
1686
1687 if let Some(handle2) = lhm.entry_handle(&2) {
1688 assert_eq!(lhm.get_entry(&handle2), Some((&2, &"b")));
1689 } else {
1690 panic!("Expected valid handle for key 2");
1691 }
1692
1693 if let Some(handle3) = lhm.entry_handle(&3) {
1694 assert_eq!(lhm.get_entry(&handle3), Some((&3, &"c")));
1695 } else {
1696 panic!("Expected valid handle for key 3");
1697 }
1698
1699 // Test invalid handle
1700 let invalid_handle = crate::lhmap::entry::EntryHandle::<u16, &str>::default();
1701 assert_eq!(lhm.get_entry(&invalid_handle), None);
1702 }
1703
1704 #[test]
1705 fn test_get_entry_does_not_affect_order() {
1706 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
1707 lhm.put(1, "a");
1708 lhm.put(2, "b");
1709 lhm.put(3, "c");
1710
1711 // Initial order: [1, 2, 3]
1712 let keys_before: Vec<_> = lhm.keys().copied().collect();
1713 assert_eq!(keys_before, vec![1, 2, 3]);
1714
1715 // Get entry using handle - should NOT affect AccessOrder
1716 if let Some(handle1) = lhm.entry_handle(&1) {
1717 assert_eq!(lhm.get_entry(&handle1), Some((&1, &"a")));
1718 }
1719
1720 // Order should remain the same
1721 let keys_after: Vec<_> = lhm.keys().copied().collect();
1722 assert_eq!(keys_after, vec![1, 2, 3]);
1723 assert_eq!(keys_before, keys_after);
1724
1725 // Compare with regular get() which DOES affect AccessOrder
1726 assert_eq!(lhm.get(&1), Some(&"a"));
1727 let keys_after_get: Vec<_> = lhm.keys().copied().collect();
1728 assert_eq!(keys_after_get, vec![2, 3, 1]); // 1 moved to tail
1729 }
1730
1731 #[test]
1732 fn test_get_entry_invalid_after_removal() {
1733 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1734 lhm.put(1, "a");
1735 lhm.put(2, "b");
1736
1737 // Get handle for key 1
1738 let handle1 = lhm.entry_handle(&1).expect("Expected valid handle");
1739
1740 // Verify handle works initially
1741 assert_eq!(lhm.get_entry(&handle1), Some((&1, &"a")));
1742
1743 // Remove the entry
1744 assert_eq!(lhm.remove(&1), Some("a"));
1745
1746 // Now the handle should be invalid
1747 assert_eq!(lhm.get_entry(&handle1), None);
1748 }
1749
1750 #[test]
1751 fn test_get_entry_insertion_order() {
1752 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1753 lhm.put(1, "a");
1754 lhm.put(2, "b");
1755 lhm.put(3, "c");
1756
1757 // Get all handles
1758 let handle1 = lhm.entry_handle(&1).unwrap();
1759 let handle2 = lhm.entry_handle(&2).unwrap();
1760 let handle3 = lhm.entry_handle(&3).unwrap();
1761
1762 // Access entries in different order - should not affect iteration order
1763 assert_eq!(lhm.get_entry(&handle3), Some((&3, &"c")));
1764 assert_eq!(lhm.get_entry(&handle1), Some((&1, &"a")));
1765 assert_eq!(lhm.get_entry(&handle2), Some((&2, &"b")));
1766
1767 // Iteration order should remain unchanged
1768 let keys: Vec<_> = lhm.keys().copied().collect();
1769 assert_eq!(keys, vec![1, 2, 3]);
1770 }
1771
1772 #[test]
1773 fn test_get_entry_with_handle_operations() {
1774 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1775 lhm.put(1, "a");
1776 lhm.put(2, "b");
1777 lhm.put(3, "c");
1778
1779 // Get handle and verify initial state
1780 let handle2 = lhm.entry_handle(&2).unwrap();
1781 assert_eq!(lhm.get_entry(&handle2), Some((&2, &"b")));
1782
1783 // Move entry to tail using handle
1784 assert!(lhm.make_tail(handle2.clone()));
1785
1786 // Handle should still be valid and return same data
1787 assert_eq!(lhm.get_entry(&handle2), Some((&2, &"b")));
1788
1789 // But iteration order should have changed
1790 let keys: Vec<_> = lhm.keys().copied().collect();
1791 assert_eq!(keys, vec![1, 3, 2]);
1792
1793 // Move entry to head using handle
1794 assert!(lhm.make_head(handle2.clone()));
1795
1796 // Handle should still be valid
1797 assert_eq!(lhm.get_entry(&handle2), Some((&2, &"b")));
1798
1799 // Iteration order should have changed again
1800 let keys: Vec<_> = lhm.keys().copied().collect();
1801 assert_eq!(keys, vec![2, 1, 3]);
1802 }
1803
1804 #[test]
1805 fn test_get_key_basic() {
1806 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1807 lhm.put(1, "a");
1808 lhm.put(2, "b");
1809 lhm.put(3, "c");
1810
1811 // Test getting valid keys
1812 if let Some(handle1) = lhm.entry_handle(&1) {
1813 assert_eq!(lhm.get_key(&handle1), Some(&1));
1814 } else {
1815 panic!("Expected valid handle for key 1");
1816 }
1817
1818 if let Some(handle2) = lhm.entry_handle(&2) {
1819 assert_eq!(lhm.get_key(&handle2), Some(&2));
1820 } else {
1821 panic!("Expected valid handle for key 2");
1822 }
1823
1824 if let Some(handle3) = lhm.entry_handle(&3) {
1825 assert_eq!(lhm.get_key(&handle3), Some(&3));
1826 } else {
1827 panic!("Expected valid handle for key 3");
1828 }
1829
1830 // Test invalid handle
1831 let invalid_handle = crate::lhmap::entry::EntryHandle::<u16, &str>::default();
1832 assert_eq!(lhm.get_key(&invalid_handle), None);
1833 }
1834
1835 #[test]
1836 fn test_get_key_does_not_affect_order() {
1837 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
1838 lhm.put(1, "a");
1839 lhm.put(2, "b");
1840 lhm.put(3, "c");
1841
1842 // Initial order: [1, 2, 3]
1843 let keys_before: Vec<_> = lhm.keys().copied().collect();
1844 assert_eq!(keys_before, vec![1, 2, 3]);
1845
1846 // Get key using handle - should NOT affect AccessOrder
1847 if let Some(handle1) = lhm.entry_handle(&1) {
1848 assert_eq!(lhm.get_key(&handle1), Some(&1));
1849 }
1850
1851 // Order should remain the same
1852 let keys_after: Vec<_> = lhm.keys().copied().collect();
1853 assert_eq!(keys_after, vec![1, 2, 3]);
1854 assert_eq!(keys_before, keys_after);
1855 }
1856
1857 #[test]
1858 fn test_get_key_invalid_after_removal() {
1859 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1860 lhm.put(1, "a");
1861 lhm.put(2, "b");
1862
1863 // Get handle for key 1
1864 let handle1 = lhm.entry_handle(&1).expect("Expected valid handle");
1865
1866 // Verify handle works initially
1867 assert_eq!(lhm.get_key(&handle1), Some(&1));
1868
1869 // Remove the entry
1870 assert_eq!(lhm.remove(&1), Some("a"));
1871
1872 // Now the handle should be invalid
1873 assert_eq!(lhm.get_key(&handle1), None);
1874 }
1875
1876 #[test]
1877 fn test_get_value_basic() {
1878 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1879 lhm.put(1, "a");
1880 lhm.put(2, "b");
1881 lhm.put(3, "c");
1882
1883 // Test getting valid values
1884 if let Some(handle1) = lhm.entry_handle(&1) {
1885 assert_eq!(lhm.get_value(&handle1), Some(&"a"));
1886 } else {
1887 panic!("Expected valid handle for key 1");
1888 }
1889
1890 if let Some(handle2) = lhm.entry_handle(&2) {
1891 assert_eq!(lhm.get_value(&handle2), Some(&"b"));
1892 } else {
1893 panic!("Expected valid handle for key 2");
1894 }
1895
1896 if let Some(handle3) = lhm.entry_handle(&3) {
1897 assert_eq!(lhm.get_value(&handle3), Some(&"c"));
1898 } else {
1899 panic!("Expected valid handle for key 3");
1900 }
1901
1902 // Test invalid handle
1903 let invalid_handle = crate::lhmap::entry::EntryHandle::<u16, &str>::default();
1904 assert_eq!(lhm.get_value(&invalid_handle), None);
1905 }
1906
1907 #[test]
1908 fn test_get_value_does_not_affect_order() {
1909 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
1910 lhm.put(1, "a");
1911 lhm.put(2, "b");
1912 lhm.put(3, "c");
1913
1914 // Initial order: [1, 2, 3]
1915 let keys_before: Vec<_> = lhm.keys().copied().collect();
1916 assert_eq!(keys_before, vec![1, 2, 3]);
1917
1918 // Get value using handle - should NOT affect AccessOrder
1919 if let Some(handle1) = lhm.entry_handle(&1) {
1920 assert_eq!(lhm.get_value(&handle1), Some(&"a"));
1921 }
1922
1923 // Order should remain the same
1924 let keys_after: Vec<_> = lhm.keys().copied().collect();
1925 assert_eq!(keys_after, vec![1, 2, 3]);
1926 assert_eq!(keys_before, keys_after);
1927 }
1928
1929 #[test]
1930 fn test_get_value_invalid_after_removal() {
1931 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
1932 lhm.put(1, "a");
1933 lhm.put(2, "b");
1934
1935 // Get handle for key 1
1936 let handle1 = lhm.entry_handle(&1).expect("Expected valid handle");
1937
1938 // Verify handle works initially
1939 assert_eq!(lhm.get_value(&handle1), Some(&"a"));
1940
1941 // Remove the entry
1942 assert_eq!(lhm.remove(&1), Some("a"));
1943
1944 // Now the handle should be invalid
1945 assert_eq!(lhm.get_value(&handle1), None);
1946 }
1947
1948 #[test]
1949 fn test_get_value_mut_basic() {
1950 let mut lhm = LinkedHashMap::<u16, String>::new(10, Order::InsertionOrder, None);
1951 lhm.put(1, "a".to_string());
1952 lhm.put(2, "b".to_string());
1953 lhm.put(3, "c".to_string());
1954
1955 // Test getting and modifying valid values
1956 if let Some(handle1) = lhm.entry_handle(&1) {
1957 if let Some(value) = lhm.get_value_mut(&handle1) {
1958 assert_eq!(value, &"a".to_string());
1959 value.push_str("_modified");
1960 assert_eq!(value, &"a_modified".to_string());
1961 } else {
1962 panic!("Expected valid mutable value for key 1");
1963 }
1964 } else {
1965 panic!("Expected valid handle for key 1");
1966 }
1967
1968 // Verify the change persisted
1969 if let Some(handle1) = lhm.entry_handle(&1) {
1970 assert_eq!(lhm.get_value(&handle1), Some(&"a_modified".to_string()));
1971 }
1972
1973 // Test invalid handle
1974 let invalid_handle = crate::lhmap::entry::EntryHandle::<u16, String>::default();
1975 assert_eq!(lhm.get_value_mut(&invalid_handle), None);
1976 }
1977
1978 #[test]
1979 fn test_get_value_mut_does_not_affect_order() {
1980 let mut lhm = LinkedHashMap::<u16, String>::new(10, Order::AccessOrder, None);
1981 lhm.put(1, "a".to_string());
1982 lhm.put(2, "b".to_string());
1983 lhm.put(3, "c".to_string());
1984
1985 // Initial order: [1, 2, 3]
1986 let keys_before: Vec<_> = lhm.keys().copied().collect();
1987 assert_eq!(keys_before, vec![1, 2, 3]);
1988
1989 // Modify value using handle - should NOT affect AccessOrder
1990 if let Some(handle1) = lhm.entry_handle(&1) {
1991 if let Some(value) = lhm.get_value_mut(&handle1) {
1992 value.push_str("_modified");
1993 }
1994 }
1995
1996 // Order should remain the same even after mutation
1997 let keys_after: Vec<_> = lhm.keys().copied().collect();
1998 assert_eq!(keys_after, vec![1, 2, 3]);
1999 assert_eq!(keys_before, keys_after);
2000
2001 // Verify the modification worked
2002 if let Some(handle1) = lhm.entry_handle(&1) {
2003 assert_eq!(lhm.get_value(&handle1), Some(&"a_modified".to_string()));
2004 }
2005 }
2006
2007 #[test]
2008 fn test_get_value_mut_invalid_after_removal() {
2009 let mut lhm = LinkedHashMap::<u16, String>::new(10, Order::InsertionOrder, None);
2010 lhm.put(1, "a".to_string());
2011 lhm.put(2, "b".to_string());
2012
2013 // Get handle for key 1
2014 let handle1 = lhm.entry_handle(&1).expect("Expected valid handle");
2015
2016 // Verify handle works initially
2017 if let Some(value) = lhm.get_value_mut(&handle1) {
2018 value.push_str("_test");
2019 }
2020 assert_eq!(lhm.get_value(&lhm.entry_handle(&1).unwrap()), Some(&"a_test".to_string()));
2021
2022 // Remove the entry
2023 assert_eq!(lhm.remove(&1), Some("a_test".to_string()));
2024
2025 // Now the handle should be invalid
2026 assert_eq!(lhm.get_value_mut(&handle1), None);
2027 }
2028
2029 #[test]
2030 fn test_get_key_value_mut_integration() {
2031 let mut lhm = LinkedHashMap::<u16, String>::new(10, Order::InsertionOrder, None);
2032 lhm.put(1, "a".to_string());
2033 lhm.put(2, "b".to_string());
2034 lhm.put(3, "c".to_string());
2035
2036 // Get handle and test all access methods
2037 if let Some(handle2) = lhm.entry_handle(&2) {
2038 // Test key access
2039 assert_eq!(lhm.get_key(&handle2), Some(&2));
2040
2041 // Test value access
2042 assert_eq!(lhm.get_value(&handle2), Some(&"b".to_string()));
2043
2044 // Test mutable value access and modification
2045 if let Some(value) = lhm.get_value_mut(&handle2) {
2046 value.push_str("_updated");
2047 }
2048
2049 // Verify modification through immutable access
2050 assert_eq!(lhm.get_value(&handle2), Some(&"b_updated".to_string()));
2051
2052 // Test handle operations still work after mutations
2053 assert!(lhm.make_tail(handle2.clone()));
2054
2055 // Verify all access methods still work after repositioning
2056 assert_eq!(lhm.get_key(&handle2), Some(&2));
2057 assert_eq!(lhm.get_value(&handle2), Some(&"b_updated".to_string()));
2058 } else {
2059 panic!("Expected valid handle for key 2");
2060 }
2061
2062 // Verify final state
2063 let keys: Vec<_> = lhm.keys().copied().collect();
2064 assert_eq!(keys, vec![1, 3, 2]); // 2 moved to tail
2065
2066 let values: Vec<_> = lhm.values().cloned().collect();
2067 assert_eq!(values, vec!["a".to_string(), "c".to_string(), "b_updated".to_string()]);
2068 }
2069
2070 #[test]
2071 fn test_make_head_basic() {
2072 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
2073 lhm.put(1, "a");
2074 lhm.put(2, "b");
2075 lhm.put(3, "c");
2076
2077 // Initial order: [1, 2, 3]
2078 let keys: Vec<_> = lhm.keys().copied().collect();
2079 assert_eq!(keys, vec![1, 2, 3]);
2080
2081 // Move key 3 to head
2082 if let Some(handle) = lhm.entry_handle(&3) {
2083 assert!(lhm.make_head(handle));
2084 }
2085
2086 // Order should now be [3, 1, 2]
2087 let keys: Vec<_> = lhm.keys().copied().collect();
2088 assert_eq!(keys, vec![3, 1, 2]);
2089
2090 // Values should remain unchanged
2091 assert_eq!(lhm.get(&1), Some(&"a"));
2092 assert_eq!(lhm.get(&2), Some(&"b"));
2093 assert_eq!(lhm.get(&3), Some(&"c"));
2094 }
2095
2096 #[test]
2097 fn test_make_head_already_at_head() {
2098 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
2099 lhm.put(1, "a");
2100 lhm.put(2, "b");
2101 lhm.put(3, "c");
2102
2103 // Move key 1 to head (it's already at head)
2104 if let Some(handle) = lhm.entry_handle(&1) {
2105 assert!(lhm.make_head(handle));
2106 }
2107
2108 // Order should remain the same: [1, 2, 3]
2109 let keys: Vec<_> = lhm.keys().copied().collect();
2110 assert_eq!(keys, vec![1, 2, 3]);
2111 }
2112
2113 #[test]
2114 fn test_make_head_access_order() {
2115 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
2116 lhm.put(1, "a");
2117 lhm.put(2, "b");
2118 lhm.put(3, "c");
2119
2120 // Initial order: [1, 2, 3]
2121 let keys: Vec<_> = lhm.keys().copied().collect();
2122 assert_eq!(keys, vec![1, 2, 3]);
2123
2124 // Move key 2 to head using handle
2125 if let Some(handle) = lhm.entry_handle(&2) {
2126 assert!(lhm.make_head(handle));
2127 }
2128
2129 // Order should now be [2, 1, 3]
2130 let keys: Vec<_> = lhm.keys().copied().collect();
2131 assert_eq!(keys, vec![2, 1, 3]);
2132 }
2133
2134 #[test]
2135 fn test_make_head_invalid_handle() {
2136 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
2137 lhm.put(1, "a");
2138
2139 // Create a default handle (invalid)
2140 let default_handle = crate::lhmap::entry::EntryHandle::<u16, &str>::default();
2141
2142 // Try to use it - should return false
2143 assert_eq!(lhm.make_head(default_handle), false);
2144 }
2145
2146 #[test]
2147 fn test_remove_head_basic() {
2148 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
2149 lhm.put(1, "a");
2150 lhm.put(2, "b");
2151 lhm.put(3, "c");
2152
2153 // Remove head entries in order
2154 assert_eq!(lhm.remove_head(), Some((1, "a")));
2155 assert_eq!(lhm.len(), 2);
2156
2157 assert_eq!(lhm.remove_head(), Some((2, "b")));
2158 assert_eq!(lhm.len(), 1);
2159
2160 assert_eq!(lhm.remove_head(), Some((3, "c")));
2161 assert_eq!(lhm.len(), 0);
2162
2163 // Empty map returns None
2164 assert_eq!(lhm.remove_head(), None);
2165 }
2166
2167 #[test]
2168 fn test_remove_head_access_order() {
2169 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
2170 lhm.put(1, "a");
2171 lhm.put(2, "b");
2172 lhm.put(3, "c");
2173
2174 // Access key 2, making it most recently used (moves to tail)
2175 lhm.get(&2);
2176
2177 // Order should now be [1, 3, 2]
2178 let keys: Vec<_> = lhm.keys().copied().collect();
2179 assert_eq!(keys, vec![1, 3, 2]);
2180
2181 // Remove head should remove 1 (least recently used)
2182 assert_eq!(lhm.remove_head(), Some((1, "a")));
2183
2184 let keys: Vec<_> = lhm.keys().copied().collect();
2185 assert_eq!(keys, vec![3, 2]);
2186 }
2187
2188 #[test]
2189 fn test_remove_tail_basic() {
2190 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
2191 lhm.put(1, "a");
2192 lhm.put(2, "b");
2193 lhm.put(3, "c");
2194
2195 // Remove tail entries in reverse order
2196 assert_eq!(lhm.remove_tail(), Some((3, "c")));
2197 assert_eq!(lhm.len(), 2);
2198
2199 assert_eq!(lhm.remove_tail(), Some((2, "b")));
2200 assert_eq!(lhm.len(), 1);
2201
2202 assert_eq!(lhm.remove_tail(), Some((1, "a")));
2203 assert_eq!(lhm.len(), 0);
2204
2205 // Empty map returns None
2206 assert_eq!(lhm.remove_tail(), None);
2207 }
2208
2209 #[test]
2210 fn test_remove_tail_access_order() {
2211 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::AccessOrder, None);
2212 lhm.put(1, "a");
2213 lhm.put(2, "b");
2214 lhm.put(3, "c");
2215
2216 // Access key 1, making it most recently used (moves to tail)
2217 lhm.get(&1);
2218
2219 // Order should now be [2, 3, 1]
2220 let keys: Vec<_> = lhm.keys().copied().collect();
2221 assert_eq!(keys, vec![2, 3, 1]);
2222
2223 // Remove tail should remove 1 (most recently used)
2224 assert_eq!(lhm.remove_tail(), Some((1, "a")));
2225
2226 let keys: Vec<_> = lhm.keys().copied().collect();
2227 assert_eq!(keys, vec![2, 3]);
2228 }
2229
2230 #[test]
2231 fn test_remove_empty_map() {
2232 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
2233
2234 // Both methods should return None for empty map
2235 assert_eq!(lhm.remove_head(), None);
2236 assert_eq!(lhm.remove_tail(), None);
2237 }
2238
2239 #[test]
2240 fn test_remove_single_element() {
2241 // Test remove_head with single element
2242 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
2243 lhm.put(1, "a");
2244 assert_eq!(lhm.remove_head(), Some((1, "a")));
2245 assert!(lhm.is_empty());
2246
2247 // Test remove_tail with single element
2248 let mut lhm2 = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
2249 lhm2.put(1, "a");
2250 assert_eq!(lhm2.remove_tail(), Some((1, "a")));
2251 assert!(lhm2.is_empty());
2252 }
2253
2254 #[test]
2255 fn test_make_head_and_tail_integration() {
2256 let mut lhm = LinkedHashMap::<u16, &str>::new(10, Order::InsertionOrder, None);
2257 lhm.put(1, "a");
2258 lhm.put(2, "b");
2259 lhm.put(3, "c");
2260 lhm.put(4, "d");
2261
2262 // Initial order: [1, 2, 3, 4]
2263 let keys: Vec<_> = lhm.keys().copied().collect();
2264 assert_eq!(keys, vec![1, 2, 3, 4]);
2265
2266 // Move 3 to head: [3, 1, 2, 4]
2267 if let Some(handle) = lhm.entry_handle(&3) {
2268 assert!(lhm.make_head(handle));
2269 }
2270 let keys: Vec<_> = lhm.keys().copied().collect();
2271 assert_eq!(keys, vec![3, 1, 2, 4]);
2272
2273 // Move 1 to tail: [3, 2, 4, 1]
2274 if let Some(handle) = lhm.entry_handle(&1) {
2275 assert!(lhm.make_tail(handle));
2276 }
2277 let keys: Vec<_> = lhm.keys().copied().collect();
2278 assert_eq!(keys, vec![3, 2, 4, 1]);
2279
2280 // Remove head and tail
2281 assert_eq!(lhm.remove_head(), Some((3, "c")));
2282 assert_eq!(lhm.remove_tail(), Some((1, "a")));
2283
2284 // Should have [2, 4] left
2285 let keys: Vec<_> = lhm.keys().copied().collect();
2286 assert_eq!(keys, vec![2, 4]);
2287 }
2288
2289 #[test]
2290 fn test_head() {
2291 let mut lhm: LinkedHashMap<u16, &str> = LinkedHashMap::new(10, Order::InsertionOrder, None);
2292
2293 // Empty map should return None
2294 assert_eq!(lhm.head(), None);
2295
2296 // Add some entries
2297 lhm.put(1, "a");
2298 assert_eq!(lhm.head(), Some((&1, &"a")));
2299
2300 lhm.put(2, "b");
2301 assert_eq!(lhm.head(), Some((&1, &"a"))); // Head should still be first inserted
2302
2303 lhm.put(3, "c");
2304 assert_eq!(lhm.head(), Some((&1, &"a"))); // Head should still be first inserted
2305
2306 // Remove head and check next becomes head
2307 assert_eq!(lhm.remove_head(), Some((1, "a")));
2308 assert_eq!(lhm.head(), Some((&2, &"b")));
2309
2310 assert_eq!(lhm.remove_head(), Some((2, "b")));
2311 assert_eq!(lhm.head(), Some((&3, &"c")));
2312
2313 assert_eq!(lhm.remove_head(), Some((3, "c")));
2314 assert_eq!(lhm.head(), None);
2315 }
2316
2317 #[test]
2318 fn test_head_access_order() {
2319 let mut lhm: LinkedHashMap<u16, &str> = LinkedHashMap::new(10, Order::AccessOrder, None);
2320
2321 // Add entries
2322 lhm.put(1, "a");
2323 lhm.put(2, "b");
2324 lhm.put(3, "c");
2325
2326 // Head should be least recently accessed (first inserted)
2327 assert_eq!(lhm.head(), Some((&1, &"a")));
2328
2329 // Access element 1 - it should move to tail, making 2 the new head
2330 lhm.get(&1);
2331 assert_eq!(lhm.head(), Some((&2, &"b")));
2332
2333 // Access element 2 - it should move to tail, making 3 the new head
2334 lhm.get(&2);
2335 assert_eq!(lhm.head(), Some((&3, &"c")));
2336 }
2337
2338 #[test]
2339 fn test_tail() {
2340 let mut lhm: LinkedHashMap<u16, &str> = LinkedHashMap::new(10, Order::InsertionOrder, None);
2341
2342 // Empty map should return None
2343 assert_eq!(lhm.tail(), None);
2344
2345 // Add some entries
2346 lhm.put(1, "a");
2347 assert_eq!(lhm.tail(), Some((&1, &"a")));
2348
2349 lhm.put(2, "b");
2350 assert_eq!(lhm.tail(), Some((&2, &"b"))); // Tail should be last inserted
2351
2352 lhm.put(3, "c");
2353 assert_eq!(lhm.tail(), Some((&3, &"c"))); // Tail should be last inserted
2354
2355 // Remove tail and check previous becomes tail
2356 assert_eq!(lhm.remove_tail(), Some((3, "c")));
2357 assert_eq!(lhm.tail(), Some((&2, &"b")));
2358
2359 assert_eq!(lhm.remove_tail(), Some((2, "b")));
2360 assert_eq!(lhm.tail(), Some((&1, &"a")));
2361
2362 assert_eq!(lhm.remove_tail(), Some((1, "a")));
2363 assert_eq!(lhm.tail(), None);
2364 }
2365
2366 #[test]
2367 fn test_tail_access_order() {
2368 let mut lhm: LinkedHashMap<u16, &str> = LinkedHashMap::new(10, Order::AccessOrder, None);
2369
2370 // Add entries
2371 lhm.put(1, "a");
2372 lhm.put(2, "b");
2373 lhm.put(3, "c");
2374
2375 // Tail should be most recently accessed (last inserted)
2376 assert_eq!(lhm.tail(), Some((&3, &"c")));
2377
2378 // Access element 1 - it should move to tail
2379 lhm.get(&1);
2380 assert_eq!(lhm.tail(), Some((&1, &"a")));
2381
2382 // Access element 2 - it should move to tail
2383 lhm.get(&2);
2384 assert_eq!(lhm.tail(), Some((&2, &"b")));
2385 }
2386}