1use super::{CacheBuilder, IndexDeque, Iter, Slab, SlabEntry, SENTINEL};
2use crate::Policy;
3
4use hashbrown::HashTable;
5use std::{
6 borrow::Borrow,
7 collections::hash_map::RandomState,
8 fmt,
9 hash::{BuildHasher, Hash},
10};
11
12pub struct Cache<K, V, S = RandomState> {
86 max_capacity: Option<u64>,
87 entry_count: u64,
88 table: HashTable<u32>,
89 build_hasher: S,
90 slab: Slab<K, V>,
91 deque: IndexDeque,
92}
93
94impl<K, V, S> fmt::Debug for Cache<K, V, S>
95where
96 K: fmt::Debug + Eq + Hash,
97 V: fmt::Debug,
98 S: BuildHasher + Clone,
99{
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 let mut d_map = f.debug_map();
102
103 for (k, v) in self.iter() {
104 d_map.entry(&k, &v);
105 }
106
107 d_map.finish()
108 }
109}
110
111impl<K, V> Cache<K, V, RandomState>
112where
113 K: Hash + Eq,
114{
115 pub fn new(max_capacity: u64) -> Self {
122 let build_hasher = RandomState::default();
123 Self::with_everything(Some(max_capacity), None, build_hasher)
124 }
125
126 pub fn builder() -> CacheBuilder<K, V, Cache<K, V, RandomState>> {
131 CacheBuilder::default()
132 }
133}
134
135impl<K, V, S> Cache<K, V, S> {
139 pub fn policy(&self) -> Policy {
144 Policy::new(self.max_capacity)
145 }
146
147 pub fn entry_count(&self) -> u64 {
167 self.entry_count
168 }
169
170 pub fn weighted_size(&self) -> u64 {
174 self.entry_count
175 }
176}
177
178impl<K, V, S> Cache<K, V, S>
179where
180 K: Hash + Eq,
181 S: BuildHasher + Clone,
182{
183 pub(crate) fn with_everything(
184 max_capacity: Option<u64>,
185 initial_capacity: Option<usize>,
186 build_hasher: S,
187 ) -> Self {
188 let init_cap = initial_capacity.unwrap_or_default();
189
190 Self {
191 max_capacity,
192 entry_count: 0,
193 table: HashTable::with_capacity(init_cap),
194 build_hasher,
195 slab: if init_cap > 0 {
196 Slab::with_capacity(init_cap)
197 } else {
198 Slab::new()
199 },
200 deque: IndexDeque::default(),
201 }
202 }
203
204 #[inline]
212 pub fn contains_key<Q>(&self, key: &Q) -> bool
213 where
214 K: Borrow<Q>,
215 Q: Hash + Eq + ?Sized,
216 {
217 let hash = self.hash(key);
218 self.table
219 .find(hash, |&idx| self.slab.get(idx).key.borrow() == key)
220 .is_some()
221 }
222
223 #[inline]
228 pub fn get<Q>(&mut self, key: &Q) -> Option<&V>
229 where
230 K: Borrow<Q>,
231 Q: Hash + Eq + ?Sized,
232 {
233 let hash = self.hash(key);
234
235 let idx = match self
236 .table
237 .find(hash, |&idx| self.slab.get(idx).key.borrow() == key)
238 {
239 Some(&idx) => idx,
240 None => return None,
241 };
242
243 self.slab.get_mut(idx).visited = true;
244 Some(&self.slab.get(idx).value)
245 }
246
247 #[inline]
271 pub fn peek<Q>(&self, key: &Q) -> Option<&V>
272 where
273 K: Borrow<Q>,
274 Q: Hash + Eq + ?Sized,
275 {
276 let hash = self.hash(key);
277 let idx = self
278 .table
279 .find(hash, |&idx| self.slab.get(idx).key.borrow() == key)?;
280 Some(&self.slab.get(*idx).value)
281 }
282
283 #[inline]
308 pub fn get_or_insert_with<F>(&mut self, key: K, f: F) -> &V
309 where
310 F: FnOnce() -> V,
311 {
312 let hash = self.hash(&key);
313
314 if let Some(&idx) = self
315 .table
316 .find(hash, |&idx| self.slab.get(idx).key.borrow() == &key)
317 {
318 self.slab.get_mut(idx).visited = true;
319 return &self.slab.get(idx).value;
320 }
321
322 let value = f();
323
324 if !self.has_enough_capacity(1, self.entry_count) {
325 self.sieve_evict_one();
326 }
327
328 let slab_entry = SlabEntry {
329 key,
330 value,
331 hash,
332 visited: false,
333 prev: SENTINEL,
334 next: SENTINEL,
335 };
336 let idx = self.slab.allocate(slab_entry);
337
338 let slab = &self.slab;
339 self.table
340 .insert_unique(hash, idx, |&existing_idx| slab.get(existing_idx).hash);
341
342 self.deque.push_back(&mut self.slab, idx);
343 self.entry_count += 1;
344
345 &self.slab.get(idx).value
346 }
347
348 #[inline]
352 pub fn insert(&mut self, key: K, value: V) {
353 let hash = self.hash(&key);
354
355 if let Some(&idx) = self
356 .table
357 .find(hash, |&idx| self.slab.get(idx).key.borrow() == &key)
358 {
359 let entry = self.slab.get_mut(idx);
360 entry.value = value;
361 entry.visited = true;
362 return;
363 }
364
365 if !self.has_enough_capacity(1, self.entry_count) {
366 if self.max_capacity == Some(0) {
367 return;
368 }
369
370 self.sieve_evict_one();
371 }
372
373 let slab_entry = SlabEntry {
374 key,
375 value,
376 hash,
377 visited: false,
378 prev: SENTINEL,
379 next: SENTINEL,
380 };
381 let idx = self.slab.allocate(slab_entry);
382
383 let slab = &self.slab;
384 self.table
385 .insert_unique(hash, idx, |&existing_idx| slab.get(existing_idx).hash);
386
387 self.deque.push_back(&mut self.slab, idx);
388 self.entry_count += 1;
389 }
390
391 #[inline]
396 pub fn invalidate<Q>(&mut self, key: &Q)
397 where
398 K: Borrow<Q>,
399 Q: Hash + Eq + ?Sized,
400 {
401 let hash = self.hash(key);
402 let slab = &self.slab;
403 if let Ok(entry) = self
404 .table
405 .find_entry(hash, |&idx| slab.get(idx).key.borrow() == key)
406 {
407 let (idx, _) = entry.remove();
408 self.deque.advance_hand_past(&self.slab, idx);
409 self.deque.unlink(&mut self.slab, idx);
410 self.slab.deallocate(idx);
411 self.entry_count -= 1;
412 }
413 }
414
415 #[inline]
420 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
421 where
422 K: Borrow<Q>,
423 Q: Hash + Eq + ?Sized,
424 {
425 let hash = self.hash(key);
426 let slab = &self.slab;
427 if let Ok(entry) = self
428 .table
429 .find_entry(hash, |&idx| slab.get(idx).key.borrow() == key)
430 {
431 let (idx, _) = entry.remove();
432 self.deque.advance_hand_past(&self.slab, idx);
433 self.deque.unlink(&mut self.slab, idx);
434 let slab_entry = self.slab.deallocate(idx);
435 self.entry_count -= 1;
436 Some(slab_entry.value)
437 } else {
438 None
439 }
440 }
441
442 #[cold]
444 #[inline(never)]
445 pub fn invalidate_all(&mut self) {
446 let old_capacity = self.table.capacity();
447 let old_table = std::mem::replace(&mut self.table, HashTable::new());
448 let old_slab = std::mem::replace(&mut self.slab, Slab::new());
449 self.deque.clear();
450 self.entry_count = 0;
451
452 drop(old_table);
453 drop(old_slab);
454
455 self.table.reserve(old_capacity, |&idx| {
456 let _ = idx;
460 0
461 });
462 }
463
464 #[cold]
470 #[inline(never)]
471 pub fn invalidate_entries_if(&mut self, mut predicate: impl FnMut(&K, &V) -> bool) {
472 let indices_to_invalidate: Vec<u32> = self
473 .slab
474 .iter()
475 .filter(|(_, entry)| predicate(&entry.key, &entry.value))
476 .map(|(idx, _)| idx)
477 .collect();
478
479 let mut invalidated = 0u64;
480 for idx in indices_to_invalidate {
481 let hash = self.slab.get(idx).hash;
482 if let Ok(entry) = self.table.find_entry(hash, |&table_idx| table_idx == idx) {
483 entry.remove();
484 self.deque.advance_hand_past(&self.slab, idx);
485 self.deque.unlink(&mut self.slab, idx);
486 self.slab.deallocate(idx);
487 invalidated += 1;
488 }
489 }
490 self.entry_count -= invalidated;
491 }
492
493 pub fn iter(&self) -> Iter<'_, K, V> {
516 Iter::new(&self.slab.entries)
517 }
518}
519
520impl<K, V, S> Cache<K, V, S>
524where
525 K: Hash + Eq,
526 S: BuildHasher + Clone,
527{
528 #[inline]
529 fn hash<Q>(&self, key: &Q) -> u64
530 where
531 K: Borrow<Q>,
532 Q: Hash + Eq + ?Sized,
533 {
534 self.build_hasher.hash_one(key)
535 }
536
537 #[inline]
538 fn has_enough_capacity(&self, candidate_weight: u32, ws: u64) -> bool {
539 self.max_capacity
540 .map(|limit| ws + candidate_weight as u64 <= limit)
541 .unwrap_or(true)
542 }
543
544 #[cold]
545 #[inline(never)]
546 fn sieve_evict_one(&mut self) {
547 if let Some(victim_idx) = self.deque.sieve_evict(&mut self.slab) {
548 let victim_hash = self.slab.get(victim_idx).hash;
549 if let Ok(entry) = self
550 .table
551 .find_entry(victim_hash, |&table_idx| table_idx == victim_idx)
552 {
553 entry.remove();
554 }
555 self.slab.deallocate(victim_idx);
556 self.entry_count -= 1;
557 }
558 }
559}
560
561#[cfg(test)]
562mod tests {
563 use super::Cache;
564
565 #[test]
566 fn basic_single_thread() {
567 let mut cache = Cache::new(3);
568
569 cache.insert("a", "alice");
570 cache.insert("b", "bob");
571 assert_eq!(cache.get(&"a"), Some(&"alice"));
572 assert!(cache.contains_key(&"a"));
573 assert!(cache.contains_key(&"b"));
574 assert_eq!(cache.get(&"b"), Some(&"bob"));
575
576 cache.insert("c", "cindy");
577 assert_eq!(cache.get(&"c"), Some(&"cindy"));
578 assert!(cache.contains_key(&"c"));
579
580 assert!(cache.contains_key(&"a"));
581 assert_eq!(cache.get(&"a"), Some(&"alice"));
582 assert_eq!(cache.get(&"b"), Some(&"bob"));
583 assert!(cache.contains_key(&"b"));
584
585 cache.insert("d", "david");
588 assert_eq!(cache.entry_count(), 3);
589 assert!(cache.contains_key(&"d"));
590
591 cache.invalidate(&"b");
592 assert_eq!(cache.get(&"b"), None);
593 assert!(!cache.contains_key(&"b"));
594 }
595
596 #[test]
597 fn sieve_evicts_unvisited_entry() {
598 let mut cache = Cache::new(3);
599
600 cache.insert("a", "alice");
601 cache.insert("b", "bob");
602 cache.insert("c", "cindy");
603
604 cache.get(&"b");
606 cache.get(&"c");
607
608 cache.insert("d", "david");
611 assert_eq!(cache.entry_count(), 3);
612 assert_eq!(cache.get(&"a"), None);
613 assert!(cache.contains_key(&"b"));
614 assert!(cache.contains_key(&"c"));
615 assert!(cache.contains_key(&"d"));
616 }
617
618 #[test]
619 fn sieve_visited_entries_get_second_chance() {
620 let mut cache = Cache::new(3);
621
622 cache.insert("a", "alice");
623 cache.insert("b", "bob");
624 cache.insert("c", "cindy");
625
626 cache.get(&"a");
628 cache.get(&"b");
629 cache.get(&"c");
630
631 cache.insert("d", "david");
634 assert_eq!(cache.entry_count(), 3);
635 assert!(cache.contains_key(&"d"));
636 }
637
638 #[test]
639 fn sieve_new_entry_always_admitted() {
640 let mut cache = Cache::new(3);
641
642 cache.insert("a", "alice");
643 cache.insert("b", "bob");
644 cache.insert("c", "cindy");
645
646 for _ in 0..10 {
649 cache.get(&"a");
650 cache.get(&"b");
651 cache.get(&"c");
652 }
653
654 cache.insert("d", "david");
655 assert_eq!(cache.entry_count(), 3);
656 assert!(cache.contains_key(&"d"));
657 }
658
659 #[test]
660 fn invalidate_all() {
661 let mut cache = Cache::new(100);
662
663 cache.insert("a", "alice");
664 cache.insert("b", "bob");
665 cache.insert("c", "cindy");
666 assert_eq!(cache.get(&"a"), Some(&"alice"));
667 assert_eq!(cache.get(&"b"), Some(&"bob"));
668 assert_eq!(cache.get(&"c"), Some(&"cindy"));
669 assert!(cache.contains_key(&"a"));
670 assert!(cache.contains_key(&"b"));
671 assert!(cache.contains_key(&"c"));
672
673 cache.invalidate_all();
674
675 cache.insert("d", "david");
676
677 assert!(cache.get(&"a").is_none());
678 assert!(cache.get(&"b").is_none());
679 assert!(cache.get(&"c").is_none());
680 assert_eq!(cache.get(&"d"), Some(&"david"));
681 assert!(!cache.contains_key(&"a"));
682 assert!(!cache.contains_key(&"b"));
683 assert!(!cache.contains_key(&"c"));
684 assert!(cache.contains_key(&"d"));
685 }
686
687 #[test]
688 fn invalidate_entries_if() {
689 use std::collections::HashSet;
690
691 let mut cache = Cache::new(100);
692
693 cache.insert(0, "alice");
694 cache.insert(1, "bob");
695 cache.insert(2, "alex");
696
697 assert_eq!(cache.get(&0), Some(&"alice"));
698 assert_eq!(cache.get(&1), Some(&"bob"));
699 assert_eq!(cache.get(&2), Some(&"alex"));
700 assert!(cache.contains_key(&0));
701 assert!(cache.contains_key(&1));
702 assert!(cache.contains_key(&2));
703
704 let names = ["alice", "alex"].iter().cloned().collect::<HashSet<_>>();
705 cache.invalidate_entries_if(move |_k, &v| names.contains(v));
706
707 cache.insert(3, "alice");
708
709 assert!(cache.get(&0).is_none());
710 assert!(cache.get(&2).is_none());
711 assert_eq!(cache.get(&1), Some(&"bob"));
712 assert_eq!(cache.get(&3), Some(&"alice"));
713
714 assert!(!cache.contains_key(&0));
715 assert!(cache.contains_key(&1));
716 assert!(!cache.contains_key(&2));
717 assert!(cache.contains_key(&3));
718
719 assert_eq!(cache.table.len(), 2);
720
721 cache.invalidate_entries_if(|_k, &v| v == "alice");
722 cache.invalidate_entries_if(|_k, &v| v == "bob");
723
724 assert!(cache.get(&1).is_none());
725 assert!(cache.get(&3).is_none());
726
727 assert!(!cache.contains_key(&1));
728 assert!(!cache.contains_key(&3));
729
730 assert_eq!(cache.table.len(), 0);
731 }
732
733 #[test]
734 fn remove_decrements_entry_count() {
735 let mut cache = Cache::new(3);
736 cache.insert("a", "alice");
737 cache.insert("b", "bob");
738 assert_eq!(cache.entry_count(), 2);
739
740 let removed = cache.remove(&"a");
741 assert_eq!(removed, Some("alice"));
742 assert_eq!(cache.entry_count(), 1);
743
744 cache.remove(&"nonexistent");
745 assert_eq!(cache.entry_count(), 1);
746
747 cache.remove(&"b");
748 assert_eq!(cache.entry_count(), 0);
749 }
750
751 #[test]
752 fn invalidate_decrements_entry_count() {
753 let mut cache = Cache::new(3);
754 cache.insert("a", "alice");
755 cache.insert("b", "bob");
756 assert_eq!(cache.entry_count(), 2);
757
758 cache.invalidate(&"a");
759 assert_eq!(cache.entry_count(), 1);
760
761 cache.invalidate(&"nonexistent");
762 assert_eq!(cache.entry_count(), 1);
763
764 cache.invalidate(&"b");
765 assert_eq!(cache.entry_count(), 0);
766 }
767
768 #[test]
769 fn insert_after_remove_on_full_cache() {
770 let mut cache = Cache::new(2);
771 cache.insert("a", "alice");
772 cache.insert("b", "bob");
773 assert_eq!(cache.entry_count(), 2);
774
775 cache.remove(&"a");
776 assert_eq!(cache.entry_count(), 1);
777
778 cache.insert("c", "cindy");
779 assert_eq!(cache.entry_count(), 2);
780 assert_eq!(cache.get(&"c"), Some(&"cindy"));
781 assert_eq!(cache.get(&"b"), Some(&"bob"));
782 assert_eq!(cache.get(&"a"), None);
783 }
784
785 #[test]
786 fn insert_after_invalidate_on_full_cache() {
787 let mut cache = Cache::new(2);
788 cache.insert("a", "alice");
789 cache.insert("b", "bob");
790 assert_eq!(cache.entry_count(), 2);
791
792 cache.invalidate(&"a");
793 assert_eq!(cache.entry_count(), 1);
794
795 cache.insert("c", "cindy");
796 assert_eq!(cache.entry_count(), 2);
797 assert_eq!(cache.get(&"c"), Some(&"cindy"));
798 assert_eq!(cache.get(&"b"), Some(&"bob"));
799 assert_eq!(cache.get(&"a"), None);
800 }
801
802 #[test]
803 fn invalidate_all_panic_safety() {
804 use std::panic::catch_unwind;
805 use std::panic::AssertUnwindSafe;
806 use std::sync::atomic::{AtomicU32, Ordering};
807
808 static DROP_COUNT: AtomicU32 = AtomicU32::new(0);
809
810 struct PanicOnDrop {
811 id: u32,
812 should_panic: bool,
813 }
814
815 impl Drop for PanicOnDrop {
816 fn drop(&mut self) {
817 DROP_COUNT.fetch_add(1, Ordering::Relaxed);
818 if self.should_panic {
819 panic!("intentional panic in drop for id={}", self.id);
820 }
821 }
822 }
823
824 DROP_COUNT.store(0, Ordering::Relaxed);
825 let mut cache = Cache::new(10);
826 cache.insert(
827 1,
828 PanicOnDrop {
829 id: 1,
830 should_panic: false,
831 },
832 );
833 cache.insert(
834 2,
835 PanicOnDrop {
836 id: 2,
837 should_panic: true,
838 },
839 );
840 cache.insert(
841 3,
842 PanicOnDrop {
843 id: 3,
844 should_panic: false,
845 },
846 );
847 assert_eq!(cache.entry_count(), 3);
848
849 let result = catch_unwind(AssertUnwindSafe(|| {
850 cache.invalidate_all();
851 }));
852 assert!(result.is_err());
853
854 assert_eq!(cache.entry_count(), 0);
855 assert_eq!(cache.table.len(), 0);
856
857 cache.insert(
858 4,
859 PanicOnDrop {
860 id: 4,
861 should_panic: false,
862 },
863 );
864 assert_eq!(cache.entry_count(), 1);
865 assert!(cache.contains_key(&4));
866 }
867
868 #[test]
869 fn test_debug_format() {
870 let mut cache = Cache::new(10);
871 cache.insert('a', "alice");
872 cache.insert('b', "bob");
873 cache.insert('c', "cindy");
874
875 let debug_str = format!("{:?}", cache);
876 assert!(debug_str.starts_with('{'));
877 assert!(debug_str.contains(r#"'a': "alice""#));
878 assert!(debug_str.contains(r#"'b': "bob""#));
879 assert!(debug_str.contains(r#"'c': "cindy""#));
880 assert!(debug_str.ends_with('}'));
881 }
882
883 #[test]
884 fn sub_capacity_inserts_skip_eviction() {
885 let mut cache = Cache::new(10);
886 for i in 0u32..5 {
887 cache.insert(i, i * 10);
888 }
889 assert_eq!(cache.entry_count(), 5);
890 for i in 0u32..5 {
891 assert_eq!(cache.get(&i), Some(&(i * 10)));
892 }
893 }
894
895 #[test]
896 fn eviction_triggers_when_over_capacity() {
897 let mut cache = Cache::new(3);
898
899 cache.insert(1, "a");
900 cache.insert(2, "b");
901 cache.insert(3, "c");
902 assert_eq!(cache.entry_count(), 3);
903
904 cache.insert(4, "d");
905 assert!(cache.entry_count() <= 3);
906 }
907
908 #[test]
909 fn warmup_to_full_transition() {
910 let mut cache = Cache::new(4);
911
912 cache.insert(1, "a");
913 cache.insert(2, "b");
914 assert_eq!(cache.entry_count(), 2);
915
916 cache.insert(3, "c");
917 cache.insert(4, "d");
918 assert_eq!(cache.entry_count(), 4);
919
920 for _ in 0..5 {
921 cache.get(&1);
922 cache.get(&2);
923 cache.get(&3);
924 cache.get(&4);
925 }
926
927 cache.insert(5, "e");
928 assert!(cache.entry_count() <= 4);
929 }
930
931 #[test]
932 fn invalidate_and_remove_skip_eviction_below_capacity() {
933 let mut cache = Cache::new(10);
934 cache.insert(1, "a");
935 cache.insert(2, "b");
936 cache.insert(3, "c");
937 assert_eq!(cache.entry_count(), 3);
938
939 cache.invalidate(&1);
940 assert_eq!(cache.entry_count(), 2);
941
942 let val = cache.remove(&2);
943 assert_eq!(val, Some("b"));
944 assert_eq!(cache.entry_count(), 1);
945
946 assert_eq!(cache.get(&3), Some(&"c"));
947 }
948
949 #[test]
950 fn peek_returns_value() {
951 let mut cache = Cache::new(10);
952 cache.insert("a", "alice");
953 cache.insert("b", "bob");
954
955 assert_eq!(cache.peek(&"a"), Some(&"alice"));
956 assert_eq!(cache.peek(&"b"), Some(&"bob"));
957 }
958
959 #[test]
960 fn peek_returns_none_for_missing_key() {
961 let cache = Cache::<&str, &str>::new(10);
962 assert_eq!(cache.peek(&"missing"), None);
963 }
964
965 #[test]
966 fn peek_does_not_set_visited() {
967 let mut cache = Cache::new(3);
968
969 cache.insert("a", "alice");
970 cache.insert("b", "bob");
971 cache.insert("c", "cindy");
972
973 cache.peek(&"a");
975 cache.peek(&"b");
976 cache.peek(&"c");
977
978 cache.insert("d", "david");
981
982 assert_eq!(cache.entry_count(), 3);
984 assert!(cache.contains_key(&"d"));
985 }
986
987 #[test]
988 fn contains_key_with_shared_reference() {
989 let mut cache = Cache::new(10);
990 cache.insert("a", 1);
991 cache.insert("b", 2);
992 cache.insert("c", 3);
993
994 let cache_ref: &Cache<&str, i32> = &cache;
995 assert!(cache_ref.contains_key(&"a"));
996 assert!(cache_ref.contains_key(&"b"));
997 assert!(cache_ref.contains_key(&"c"));
998 assert!(!cache_ref.contains_key(&"d"));
999 }
1000
1001 #[test]
1002 fn zero_capacity_insert_returns_immediately() {
1003 let mut cache = Cache::new(0);
1004 cache.insert("a", "alice");
1005 assert_eq!(cache.entry_count(), 0);
1006 assert!(!cache.contains_key(&"a"));
1007 assert_eq!(cache.get(&"a"), None);
1008 }
1009
1010 #[test]
1011 fn update_existing_key_sets_visited() {
1012 let mut cache = Cache::new(3);
1013
1014 cache.insert("a", "alice");
1015 cache.insert("b", "bob");
1016 cache.insert("c", "cindy");
1017
1018 cache.insert("a", "anna");
1021 assert_eq!(cache.get(&"a"), Some(&"anna"));
1022 assert_eq!(cache.entry_count(), 3);
1023
1024 cache.insert("d", "david");
1027 assert_eq!(cache.entry_count(), 3);
1028 assert!(cache.contains_key(&"a"));
1029 assert!(cache.contains_key(&"d"));
1030 }
1031
1032 #[test]
1033 fn sieve_hand_advances_across_evictions() {
1034 let mut cache = Cache::new(3);
1035
1036 cache.insert("a", "alice");
1037 cache.insert("b", "bob");
1038 cache.insert("c", "cindy");
1039
1040 cache.insert("d", "david");
1042 assert_eq!(cache.entry_count(), 3);
1043
1044 cache.insert("e", "eve");
1046 assert_eq!(cache.entry_count(), 3);
1047
1048 cache.insert("f", "frank");
1050 assert_eq!(cache.entry_count(), 3);
1051 }
1052
1053 #[test]
1054 fn sieve_multiple_evictions_cycle() {
1055 let mut cache = Cache::new(2);
1056
1057 for i in 0u32..20 {
1058 cache.insert(i, i * 10);
1059 assert!(cache.entry_count() <= 2);
1060 }
1061
1062 assert_eq!(cache.entry_count(), 2);
1064 assert!(cache.contains_key(&19));
1065 assert!(cache.contains_key(&18));
1066 }
1067
1068 #[test]
1069 fn update_below_capacity_no_eviction() {
1070 let mut cache = Cache::new(5);
1071
1072 cache.insert("a", "alice");
1073 cache.insert("b", "bob");
1074 cache.insert("c", "cindy");
1075 assert_eq!(cache.entry_count(), 3);
1076
1077 cache.insert("b", "betty");
1079 assert_eq!(cache.entry_count(), 3);
1080 assert_eq!(cache.get(&"b"), Some(&"betty"));
1081 assert!(cache.contains_key(&"a"));
1082 assert!(cache.contains_key(&"c"));
1083 }
1084
1085 #[test]
1086 fn get_or_insert_with_basic() {
1087 let mut cache = Cache::new(10);
1088
1089 let v = cache.get_or_insert_with("a", || "alice");
1090 assert_eq!(v, &"alice");
1091 assert_eq!(cache.entry_count(), 1);
1092
1093 let v = cache.get_or_insert_with("a", || panic!("should not be called"));
1094 assert_eq!(v, &"alice");
1095 assert_eq!(cache.entry_count(), 1);
1096 }
1097
1098 #[test]
1099 fn get_or_insert_with_closure_called_only_on_miss() {
1100 let mut cache = Cache::new(10);
1101 let mut call_count = 0;
1102
1103 cache.get_or_insert_with("a", || {
1104 call_count += 1;
1105 "alice"
1106 });
1107 assert_eq!(call_count, 1);
1108
1109 cache.get_or_insert_with("a", || {
1110 call_count += 1;
1111 "anna"
1112 });
1113 assert_eq!(call_count, 1);
1114
1115 cache.get_or_insert_with("b", || {
1116 call_count += 1;
1117 "bob"
1118 });
1119 assert_eq!(call_count, 2);
1120 }
1121
1122 #[test]
1123 fn get_or_insert_with_eviction_at_capacity() {
1124 let mut cache = Cache::new(3);
1125
1126 cache.get_or_insert_with("a", || "alice");
1127 cache.get_or_insert_with("b", || "bob");
1128 cache.get_or_insert_with("c", || "cindy");
1129 assert_eq!(cache.entry_count(), 3);
1130
1131 cache.get_or_insert_with("d", || "david");
1132 assert_eq!(cache.entry_count(), 3);
1133 assert!(cache.contains_key(&"d"));
1134 }
1135
1136 #[test]
1137 fn get_or_insert_with_existing_key_no_closure() {
1138 let mut cache = Cache::new(10);
1139 cache.insert("a", "alice");
1140
1141 let v = cache.get_or_insert_with("a", || panic!("should not be called"));
1142 assert_eq!(v, &"alice");
1143 assert_eq!(cache.entry_count(), 1);
1144 }
1145
1146 #[test]
1147 fn get_or_insert_with_sets_visited_on_hit() {
1148 let mut cache = Cache::new(3);
1149
1150 cache.insert("a", "alice");
1151 cache.insert("b", "bob");
1152 cache.insert("c", "cindy");
1153
1154 cache.get_or_insert_with("a", || panic!("should not be called"));
1156
1157 cache.insert("d", "david");
1160 assert_eq!(cache.entry_count(), 3);
1161 assert!(cache.contains_key(&"a"));
1162 assert!(cache.contains_key(&"d"));
1163 }
1164
1165 #[test]
1166 fn get_or_insert_with_zero_capacity() {
1167 let mut cache = Cache::new(0);
1168
1169 let v = cache.get_or_insert_with("a", || "alice");
1171 assert_eq!(v, &"alice");
1172
1173 let v = cache.get_or_insert_with("a", || panic!("should not be called"));
1175 assert_eq!(v, &"alice");
1176
1177 let v = cache.get_or_insert_with("b", || "bob");
1179 assert_eq!(v, &"bob");
1180 assert_eq!(cache.entry_count(), 1);
1181 assert!(!cache.contains_key(&"a"));
1182 assert!(cache.contains_key(&"b"));
1183 }
1184
1185 #[test]
1186 fn get_or_insert_with_after_invalidate() {
1187 let mut cache = Cache::new(10);
1188 cache.insert("a", "alice");
1189 cache.invalidate(&"a");
1190 assert_eq!(cache.entry_count(), 0);
1191
1192 let v = cache.get_or_insert_with("a", || "anna");
1193 assert_eq!(v, &"anna");
1194 assert_eq!(cache.entry_count(), 1);
1195 }
1196
1197 #[test]
1198 fn get_or_insert_with_after_remove() {
1199 let mut cache = Cache::new(10);
1200 cache.insert("a", "alice");
1201 let removed = cache.remove(&"a");
1202 assert_eq!(removed, Some("alice"));
1203
1204 let v = cache.get_or_insert_with("a", || "anna");
1205 assert_eq!(v, &"anna");
1206 assert_eq!(cache.entry_count(), 1);
1207 }
1208}