1use super::Cached;
2use crate::lru_list::LRUList;
3use hashbrown::raw::RawTable;
4use std::cmp::Eq;
5use std::fmt;
6use std::hash::{BuildHasher, Hash, Hasher};
7
8#[cfg(feature = "ahash")]
9use ahash::RandomState;
10
11#[cfg(not(feature = "ahash"))]
12use std::collections::hash_map::RandomState;
13
14#[cfg(feature = "async")]
15use {super::CachedAsync, async_trait::async_trait, futures::Future};
16
17#[derive(Clone)]
24pub struct SizedCache<K, V> {
25 pub(super) store: RawTable<usize>,
27 pub(super) hash_builder: RandomState,
28 pub(super) order: LRUList<(K, V)>,
29 pub(super) capacity: usize,
30 pub(super) hits: u64,
31 pub(super) misses: u64,
32}
33
34impl<K, V> fmt::Debug for SizedCache<K, V>
35where
36 K: fmt::Debug,
37 V: fmt::Debug,
38{
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.debug_struct("SizedCache")
41 .field("order", &self.order)
42 .field("capacity", &self.capacity)
43 .field("hits", &self.hits)
44 .field("misses", &self.misses)
45 .finish()
46 }
47}
48
49impl<K, V> PartialEq for SizedCache<K, V>
50where
51 K: Eq + Hash + Clone,
52 V: PartialEq,
53{
54 fn eq(&self, other: &SizedCache<K, V>) -> bool {
55 self.store.len() == other.store.len() && {
56 self.order
57 .iter()
58 .all(|(key, value)| match other.get_index(other.hash(key), key) {
59 Some(i) => value == &other.order.get(i).1,
60 None => false,
61 })
62 }
63 }
64}
65
66impl<K, V> Eq for SizedCache<K, V>
67where
68 K: Eq + Hash + Clone,
69 V: PartialEq,
70{
71}
72
73impl<K: Hash + Eq + Clone, V> SizedCache<K, V> {
74 #[deprecated(since = "0.5.1", note = "method renamed to `with_size`")]
75 #[must_use]
76 pub fn with_capacity(size: usize) -> SizedCache<K, V> {
77 Self::with_size(size)
78 }
79
80 #[must_use]
86 pub fn with_size(size: usize) -> SizedCache<K, V> {
87 if size == 0 {
88 panic!("`size` of `SizedCache` must be greater than zero.");
89 }
90 SizedCache {
91 store: RawTable::with_capacity(size),
92 hash_builder: RandomState::new(),
93 order: LRUList::<(K, V)>::with_capacity(size),
94 capacity: size,
95 hits: 0,
96 misses: 0,
97 }
98 }
99
100 pub fn try_with_size(size: usize) -> std::io::Result<SizedCache<K, V>> {
106 if size == 0 {
107 return Err(std::io::Error::from_raw_os_error(22));
109 }
110
111 let store = match RawTable::try_with_capacity(size) {
112 Ok(store) => store,
113 Err(e) => {
114 let errcode = match e {
115 hashbrown::TryReserveError::AllocError { .. } => 12,
117 hashbrown::TryReserveError::CapacityOverflow => 22,
119 };
120 return Err(std::io::Error::from_raw_os_error(errcode));
121 }
122 };
123
124 Ok(SizedCache {
125 store,
126 hash_builder: RandomState::new(),
127 order: LRUList::<(K, V)>::with_capacity(size),
128 capacity: size,
129 hits: 0,
130 misses: 0,
131 })
132 }
133
134 pub(super) fn iter_order(&self) -> impl Iterator<Item = &(K, V)> {
135 self.order.iter()
136 }
137
138 pub fn key_order(&self) -> impl Iterator<Item = &K> {
141 self.order.iter().map(|(k, _v)| k)
142 }
143
144 pub fn value_order(&self) -> impl Iterator<Item = &V> {
147 self.order.iter().map(|(_k, v)| v)
148 }
149
150 fn hash<Q>(&self, key: &Q) -> u64
151 where
152 K: std::borrow::Borrow<Q>,
153 Q: std::hash::Hash + Eq + ?Sized,
154 {
155 let hasher = &mut self.hash_builder.build_hasher();
156 key.hash(hasher);
157 hasher.finish()
158 }
159
160 fn insert_index(&mut self, hash: u64, index: usize) {
161 let Self {
162 ref mut store,
163 ref order,
164 ref hash_builder,
165 ..
166 } = *self;
167 store.insert(hash, index, move |&i| {
170 let hasher = &mut hash_builder.build_hasher();
173 order.get(i).0.hash(hasher);
174 hasher.finish()
175 });
176 }
177
178 fn get_index<Q>(&self, hash: u64, key: &Q) -> Option<usize>
179 where
180 K: std::borrow::Borrow<Q>,
181 Q: std::hash::Hash + Eq + ?Sized,
182 {
183 let Self { store, order, .. } = self;
184 store
189 .get(hash, |&i| key == order.get(i).0.borrow())
190 .copied()
191 }
192
193 fn remove_index<Q>(&mut self, hash: u64, key: &Q) -> Option<usize>
194 where
195 K: std::borrow::Borrow<Q>,
196 Q: std::hash::Hash + Eq + ?Sized,
197 {
198 let Self { store, order, .. } = self;
199 store.remove_entry(hash, |&i| key == order.get(i).0.borrow())
200 }
201
202 fn check_capacity(&mut self) {
203 let Self {
204 ref mut store,
205 ref mut order,
206 ref hash_builder,
207 capacity,
208 ..
209 } = *self;
210 let len = store.len();
211 if len > capacity {
212 let index = order.back();
215 let key = &order.get(index).0;
216 let hasher = &mut hash_builder.build_hasher();
217 key.hash(hasher);
218 let hash = hasher.finish();
219
220 let order_ = ℴ
221 let erased = store.erase_entry(hash, |&i| *key == order_.get(i).0);
222 assert!(erased, "SizedCache::cache_set failed evicting cache key");
223 store.remove_entry(hash, |&i| *key == order_.get(i).0);
224 order.remove(index);
225 }
226 }
227
228 pub(super) fn get_if<F: FnOnce(&V) -> bool, Q>(&mut self, key: &Q, is_valid: F) -> Option<&V>
229 where
230 K: std::borrow::Borrow<Q>,
231 Q: std::hash::Hash + Eq + ?Sized,
232 {
233 if let Some(index) = self.get_index(self.hash(key), key) {
234 if is_valid(&self.order.get(index).1) {
235 self.order.move_to_front(index);
236 self.hits += 1;
237 return Some(&self.order.get(index).1);
238 }
239 }
240 self.misses += 1;
241 None
242 }
243
244 pub(super) fn get_mut_if<F: FnOnce(&V) -> bool, Q>(
245 &mut self,
246 key: &Q,
247 is_valid: F,
248 ) -> Option<&mut V>
249 where
250 K: std::borrow::Borrow<Q>,
251 Q: std::hash::Hash + Eq + ?Sized,
252 {
253 if let Some(index) = self.get_index(self.hash(key), key) {
254 if is_valid(&self.order.get(index).1) {
255 self.order.move_to_front(index);
256 self.hits += 1;
257 return Some(&mut self.order.get_mut(index).1);
258 }
259 }
260 self.misses += 1;
261 None
262 }
263
264 pub(super) fn get_or_set_with_if<F: FnOnce() -> V, FC: FnOnce(&V) -> bool>(
271 &mut self,
272 key: K,
273 f: F,
274 is_valid: FC,
275 ) -> (bool, bool, &mut V) {
276 let hash = self.hash(&key);
277 let index = self.get_index(hash, &key);
278 if let Some(index) = index {
279 self.hits += 1;
280 let replace_existing = {
281 let v = &self.order.get(index).1;
282 !is_valid(v)
283 };
284 if replace_existing {
285 self.order.set(index, (key, f()));
286 }
287 self.order.move_to_front(index);
288 (true, !replace_existing, &mut self.order.get_mut(index).1)
289 } else {
290 self.misses += 1;
291 let index = self.order.push_front((key, f()));
292 self.insert_index(hash, index);
293 self.check_capacity();
294 (false, false, &mut self.order.get_mut(index).1)
295 }
296 }
297
298 pub(super) fn try_get_or_set_with_if<E, F: FnOnce() -> Result<V, E>, FC: FnOnce(&V) -> bool>(
299 &mut self,
300 key: K,
301 f: F,
302 is_valid: FC,
303 ) -> Result<(bool, bool, &mut V), E> {
304 let hash = self.hash(&key);
305 let index = self.get_index(hash, &key);
306 if let Some(index) = index {
307 self.hits += 1;
308 let replace_existing = {
309 let v = &self.order.get(index).1;
310 !is_valid(v)
311 };
312 if replace_existing {
313 self.order.set(index, (key, f()?));
314 }
315 self.order.move_to_front(index);
316 Ok((true, !replace_existing, &mut self.order.get_mut(index).1))
317 } else {
318 self.misses += 1;
319 let index = self.order.push_front((key, f()?));
320 self.insert_index(hash, index);
321 self.check_capacity();
322 Ok((false, false, &mut self.order.get_mut(index).1))
323 }
324 }
325
326 #[must_use]
328 pub fn get_order(&self) -> &LRUList<(K, V)> {
329 &self.order
330 }
331
332 pub fn retain<F: Fn(&K, &V) -> bool>(&mut self, keep: F) {
333 let remove_keys = self
334 .iter_order()
335 .filter_map(|(k, v)| if keep(k, v) { None } else { Some(k.clone()) })
336 .collect::<Vec<_>>();
337 for k in remove_keys {
338 self.cache_remove(&k);
339 }
340 }
341}
342
343#[cfg(feature = "async")]
344impl<K, V> SizedCache<K, V>
345where
346 K: Hash + Eq + Clone + Send,
347{
348 pub(super) async fn get_or_set_with_if_async<F, Fut, FC>(
355 &mut self,
356 key: K,
357 f: F,
358 is_valid: FC,
359 ) -> (bool, bool, &mut V)
360 where
361 V: Send,
362 F: FnOnce() -> Fut + Send,
363 Fut: Future<Output = V> + Send,
364 FC: FnOnce(&V) -> bool,
365 {
366 let hash = self.hash(&key);
367 let index = self.get_index(hash, &key);
368 if let Some(index) = index {
369 self.hits += 1;
370 let replace_existing = {
371 let v = &self.order.get(index).1;
372 !is_valid(v)
373 };
374 if replace_existing {
375 self.order.set(index, (key, f().await));
376 }
377 self.order.move_to_front(index);
378 (true, !replace_existing, &mut self.order.get_mut(index).1)
379 } else {
380 self.misses += 1;
381 let index = self.order.push_front((key, f().await));
382 self.insert_index(hash, index);
383 self.check_capacity();
384 (false, false, &mut self.order.get_mut(index).1)
385 }
386 }
387
388 pub(super) async fn try_get_or_set_with_if_async<E, F, Fut, FC>(
389 &mut self,
390 key: K,
391 f: F,
392 is_valid: FC,
393 ) -> Result<(bool, bool, &mut V), E>
394 where
395 V: Send,
396 F: FnOnce() -> Fut + Send,
397 Fut: Future<Output = Result<V, E>> + Send,
398 FC: FnOnce(&V) -> bool,
399 {
400 let hash = self.hash(&key);
401 let index = self.get_index(hash, &key);
402 if let Some(index) = index {
403 self.hits += 1;
404 let replace_existing = {
405 let v = &self.order.get(index).1;
406 !is_valid(v)
407 };
408 if replace_existing {
409 self.order.set(index, (key, f().await?));
410 }
411 self.order.move_to_front(index);
412 Ok((true, !replace_existing, &mut self.order.get_mut(index).1))
413 } else {
414 self.misses += 1;
415 let index = self.order.push_front((key, f().await?));
416 self.insert_index(hash, index);
417 self.check_capacity();
418 Ok((false, false, &mut self.order.get_mut(index).1))
419 }
420 }
421}
422
423impl<K: Hash + Eq + Clone, V> Cached<K, V> for SizedCache<K, V> {
424 fn cache_get<Q>(&mut self, key: &Q) -> Option<&V>
425 where
426 K: std::borrow::Borrow<Q>,
427 Q: std::hash::Hash + Eq + ?Sized,
428 {
429 self.get_if(key, |_| true)
430 }
431
432 fn cache_get_mut<Q>(&mut self, key: &Q) -> std::option::Option<&mut V>
433 where
434 K: std::borrow::Borrow<Q>,
435 Q: std::hash::Hash + Eq + ?Sized,
436 {
437 self.get_mut_if(key, |_| true)
438 }
439
440 fn cache_set(&mut self, key: K, val: V) -> Option<V> {
441 let hash = self.hash(&key);
442 let v = if let Some(index) = self.get_index(hash, &key) {
443 self.order.set(index, (key, val)).map(|(_, v)| v)
444 } else {
445 let index = self.order.push_front((key, val));
446 self.insert_index(hash, index);
447 None
448 };
449 self.check_capacity();
450 v
451 }
452
453 fn cache_get_or_set_with<F: FnOnce() -> V>(&mut self, key: K, f: F) -> &mut V {
454 let (_, _, v) = self.get_or_set_with_if(key, f, |_| true);
455 v
456 }
457
458 fn cache_try_get_or_set_with<F: FnOnce() -> Result<V, E>, E>(
459 &mut self,
460 k: K,
461 f: F,
462 ) -> Result<&mut V, E> {
463 let (_, _, v) = self.try_get_or_set_with_if(k, f, |_| true)?;
464 Ok(v)
465 }
466
467 fn cache_remove<Q>(&mut self, k: &Q) -> Option<V>
468 where
469 K: std::borrow::Borrow<Q>,
470 Q: std::hash::Hash + Eq + ?Sized,
471 {
472 let hash = self.hash(k);
474 if let Some(index) = self.remove_index(hash, k) {
475 let (_key, value) = self.order.remove(index);
477 Some(value)
478 } else {
479 None
480 }
481 }
482 fn cache_clear(&mut self) {
483 self.store.clear();
485 self.order.clear();
486 }
487 fn cache_reset(&mut self) {
488 self.cache_clear();
490 }
491 fn cache_reset_metrics(&mut self) {
492 self.misses = 0;
493 self.hits = 0;
494 }
495 fn cache_size(&self) -> usize {
496 self.store.len()
497 }
498 fn cache_hits(&self) -> Option<u64> {
499 Some(self.hits)
500 }
501 fn cache_misses(&self) -> Option<u64> {
502 Some(self.misses)
503 }
504 fn cache_capacity(&self) -> Option<usize> {
505 Some(self.capacity)
506 }
507}
508
509#[cfg(feature = "async")]
510#[async_trait]
511impl<K, V> CachedAsync<K, V> for SizedCache<K, V>
512where
513 K: Hash + Eq + Clone + Send,
514{
515 async fn get_or_set_with<F, Fut>(&mut self, k: K, f: F) -> &mut V
516 where
517 V: Send,
518 F: FnOnce() -> Fut + Send,
519 Fut: Future<Output = V> + Send,
520 {
521 let (_, _, v) = self.get_or_set_with_if_async(k, f, |_| true).await;
522 v
523 }
524
525 async fn try_get_or_set_with<F, Fut, E>(&mut self, k: K, f: F) -> Result<&mut V, E>
526 where
527 V: Send,
528 F: FnOnce() -> Fut + Send,
529 Fut: Future<Output = Result<V, E>> + Send,
530 {
531 let (_, _, v) = self.try_get_or_set_with_if_async(k, f, |_| true).await?;
532 Ok(v)
533 }
534}
535
536#[cfg(test)]
537mod tests {
539 use super::*;
540
541 #[test]
542 fn sized_cache() {
543 let mut c = SizedCache::with_size(5);
544 assert!(c.cache_get(&1).is_none());
545 let misses = c.cache_misses().unwrap();
546 assert_eq!(1, misses);
547
548 assert_eq!(c.cache_set(1, 100), None);
549 assert!(c.cache_get(&1).is_some());
550 let hits = c.cache_hits().unwrap();
551 let misses = c.cache_misses().unwrap();
552 assert_eq!(1, hits);
553 assert_eq!(1, misses);
554
555 assert_eq!(c.cache_set(2, 100), None);
556 assert_eq!(c.cache_set(3, 100), None);
557 assert_eq!(c.cache_set(4, 100), None);
558 assert_eq!(c.cache_set(5, 100), None);
559
560 assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [5, 4, 3, 2, 1]);
561
562 assert_eq!(c.cache_set(6, 100), None);
563 assert_eq!(c.cache_set(7, 100), None);
564
565 assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [7, 6, 5, 4, 3]);
566
567 assert!(c.cache_get(&2).is_none());
568 assert!(c.cache_get(&3).is_some());
569
570 assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [3, 7, 6, 5, 4]);
571
572 assert_eq!(2, c.cache_misses().unwrap());
573 let size = c.cache_size();
574 assert_eq!(5, size);
575
576 c.cache_reset_metrics();
577 let hits = c.cache_hits().unwrap();
578 let misses = c.cache_misses().unwrap();
579 let size = c.cache_size();
580 assert_eq!(0, hits);
581 assert_eq!(0, misses);
582 assert_eq!(5, size);
583
584 assert_eq!(c.cache_set(7, 200), Some(100));
585
586 #[derive(Hash, Clone, Eq, PartialEq)]
587 struct MyKey {
588 v: String,
589 }
590 let mut c = SizedCache::with_size(5);
591 assert_eq!(
592 c.cache_set(
593 MyKey {
594 v: String::from("s")
595 },
596 String::from("a")
597 ),
598 None
599 );
600 assert_eq!(
601 c.cache_set(
602 MyKey {
603 v: String::from("s")
604 },
605 String::from("a")
606 ),
607 Some(String::from("a"))
608 );
609 assert_eq!(
610 c.cache_set(
611 MyKey {
612 v: String::from("s2")
613 },
614 String::from("b")
615 ),
616 None
617 );
618 assert_eq!(
619 c.cache_set(
620 MyKey {
621 v: String::from("s2")
622 },
623 String::from("b")
624 ),
625 Some(String::from("b"))
626 );
627 }
628
629 #[test]
630 fn try_new() {
631 let c: std::io::Result<SizedCache<i32, i32>> = SizedCache::try_with_size(0);
632 assert_eq!(c.unwrap_err().raw_os_error(), Some(22));
633 }
634
635 #[test]
636 fn size_cache_racing_keys_eviction_regression() {
639 let mut c = SizedCache::with_size(2);
640 assert_eq!(c.cache_set(1, 100), None);
641 assert_eq!(c.cache_set(1, 100), Some(100));
642 assert_eq!(c.cache_set(2, 100), None);
644 assert_eq!(c.cache_set(3, 100), None);
645 assert_eq!(c.cache_set(4, 100), None);
647 }
648
649 #[test]
650 fn clear() {
651 let mut c = SizedCache::with_size(3);
652
653 assert_eq!(c.cache_set(1, 100), None);
654 assert_eq!(c.cache_set(2, 200), None);
655 assert_eq!(c.cache_set(3, 300), None);
656 c.cache_clear();
657
658 assert_eq!(0, c.cache_size());
659 }
660
661 #[test]
662 fn reset() {
663 let init_capacity = 1;
664 let mut c = SizedCache::with_size(init_capacity);
665 assert_eq!(c.cache_set(1, 100), None);
666 assert_eq!(c.cache_set(2, 200), None);
667 assert_eq!(c.cache_set(3, 300), None);
668 assert!(init_capacity <= c.store.capacity());
669
670 c.cache_reset();
671
672 assert!(init_capacity <= c.store.capacity());
673 }
674
675 #[test]
676 fn remove() {
677 let mut c = SizedCache::with_size(3);
678
679 assert_eq!(c.cache_set(1, 100), None);
680 assert_eq!(c.cache_set(2, 200), None);
681 assert_eq!(c.cache_set(3, 300), None);
682
683 assert_eq!(Some(100), c.cache_remove(&1));
684 assert_eq!(2, c.cache_size());
685
686 assert_eq!(Some(200), c.cache_remove(&2));
687 assert_eq!(1, c.cache_size());
688
689 assert_eq!(None, c.cache_remove(&2));
690 assert_eq!(1, c.cache_size());
691
692 assert_eq!(Some(300), c.cache_remove(&3));
693 assert_eq!(0, c.cache_size());
694 }
695
696 #[test]
697 fn sized_cache_get_mut() {
698 let mut c = SizedCache::with_size(5);
699 assert!(c.cache_get_mut(&1).is_none());
700 let misses = c.cache_misses().unwrap();
701 assert_eq!(1, misses);
702
703 assert_eq!(c.cache_set(1, 100), None);
704 assert_eq!(*c.cache_get_mut(&1).unwrap(), 100);
705 let hits = c.cache_hits().unwrap();
706 let misses = c.cache_misses().unwrap();
707 assert_eq!(1, hits);
708 assert_eq!(1, misses);
709
710 let value = c.cache_get_mut(&1).unwrap();
711 *value = 10;
712
713 let hits = c.cache_hits().unwrap();
714 let misses = c.cache_misses().unwrap();
715 assert_eq!(2, hits);
716 assert_eq!(1, misses);
717 assert_eq!(*c.cache_get_mut(&1).unwrap(), 10);
718 }
719
720 #[test]
721 fn sized_cache_eviction_fix() {
722 let mut cache = SizedCache::<u32, ()>::with_size(3);
723
724 cache.cache_set(1, ());
725 cache.cache_set(2, ());
726 cache.cache_set(3, ());
727
728 assert!(cache.cache_get(&1).is_some());
729 assert!(cache.cache_get(&2).is_some());
730 assert!(cache.cache_get(&3).is_some());
731 assert!(cache.cache_get(&4).is_none());
732
733 cache.cache_set(4, ());
736 assert_eq!(cache.cache_size(), 3);
737 cache.cache_set(4, ());
738 assert_eq!(cache.cache_size(), 3); assert!(cache.cache_get(&1).is_none()); assert!(cache.cache_get(&2).is_some()); assert!(cache.cache_get(&3).is_some());
743 assert!(cache.cache_get(&4).is_some());
744 }
745
746 #[test]
747 fn get_or_set_with() {
748 let mut c = SizedCache::with_size(5);
749
750 assert_eq!(c.cache_get_or_set_with(0, || 0), &0);
751 assert_eq!(c.cache_get_or_set_with(1, || 1), &1);
752 assert_eq!(c.cache_get_or_set_with(2, || 2), &2);
753 assert_eq!(c.cache_get_or_set_with(3, || 3), &3);
754 assert_eq!(c.cache_get_or_set_with(4, || 4), &4);
755 assert_eq!(c.cache_get_or_set_with(5, || 5), &5);
756
757 assert_eq!(c.cache_misses(), Some(6));
758
759 assert_eq!(c.cache_get_or_set_with(0, || 0), &0);
760
761 assert_eq!(c.cache_misses(), Some(7));
762
763 assert_eq!(c.cache_get_or_set_with(0, || 42), &0);
764
765 assert_eq!(c.cache_misses(), Some(7));
766
767 assert_eq!(c.cache_get_or_set_with(1, || 1), &1);
768
769 assert_eq!(c.cache_misses(), Some(8));
770
771 c.cache_reset();
772 fn _try_get(n: usize) -> Result<usize, String> {
773 if n < 10 {
774 Ok(n)
775 } else {
776 Err("dead".to_string())
777 }
778 }
779 let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(10));
780 assert!(res.is_err());
781 assert!(c.key_order().next().is_none());
782
783 let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(1));
784 assert_eq!(res.unwrap(), &1);
785 let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(5));
786 assert_eq!(res.unwrap(), &1);
787 }
788
789 #[cfg(feature = "async")]
790 #[tokio::test]
791 async fn test_async_trait() {
792 use crate::CachedAsync;
793 let mut c = SizedCache::with_size(5);
794
795 async fn _get(n: usize) -> usize {
796 n
797 }
798
799 assert_eq!(c.get_or_set_with(0, || async { _get(0).await }).await, &0);
800 assert_eq!(c.get_or_set_with(1, || async { _get(1).await }).await, &1);
801 assert_eq!(c.get_or_set_with(2, || async { _get(2).await }).await, &2);
802 assert_eq!(c.get_or_set_with(3, || async { _get(3).await }).await, &3);
803
804 assert_eq!(c.get_or_set_with(0, || async { _get(3).await }).await, &0);
805 assert_eq!(c.get_or_set_with(1, || async { _get(3).await }).await, &1);
806 assert_eq!(c.get_or_set_with(2, || async { _get(3).await }).await, &2);
807 assert_eq!(c.get_or_set_with(3, || async { _get(1).await }).await, &3);
808
809 c.cache_reset();
810 async fn _try_get(n: usize) -> Result<usize, String> {
811 if n < 10 {
812 Ok(n)
813 } else {
814 Err("dead".to_string())
815 }
816 }
817
818 assert_eq!(
819 c.try_get_or_set_with(0, || async {
820 match _try_get(0).await {
821 Ok(n) => Ok(n),
822 Err(_) => Err("err".to_string()),
823 }
824 })
825 .await
826 .unwrap(),
827 &0
828 );
829 assert_eq!(
830 c.try_get_or_set_with(0, || async {
831 match _try_get(5).await {
832 Ok(n) => Ok(n),
833 Err(_) => Err("err".to_string()),
834 }
835 })
836 .await
837 .unwrap(),
838 &0
839 );
840
841 c.cache_reset();
842 let res: Result<&mut usize, String> = c
843 .try_get_or_set_with(0, || async { _try_get(10).await })
844 .await;
845 assert!(res.is_err());
846 assert!(c.key_order().next().is_none());
847
848 let res: Result<&mut usize, String> = c
849 .try_get_or_set_with(0, || async { _try_get(1).await })
850 .await;
851 assert_eq!(res.unwrap(), &1);
852 let res: Result<&mut usize, String> = c
853 .try_get_or_set_with(0, || async { _try_get(5).await })
854 .await;
855 assert_eq!(res.unwrap(), &1);
856 }
857}