Skip to main content

egui/cache/
cache_storage.rs

1use super::CacheTrait;
2
3/// A typemap of many caches, all implemented with [`CacheTrait`].
4///
5/// You can access egui's caches via [`crate::Memory::caches`],
6/// found with [`crate::Context::memory_mut`].
7///
8/// ```
9/// use egui::cache::{CacheStorage, ComputerMut, FrameCache};
10///
11/// #[derive(Default)]
12/// struct CharCounter {}
13/// impl ComputerMut<&str, usize> for CharCounter {
14///     fn compute(&mut self, s: &str) -> usize {
15///         s.chars().count()
16///     }
17/// }
18/// type CharCountCache<'a> = FrameCache<usize, CharCounter>;
19///
20/// # let mut cache_storage = CacheStorage::default();
21/// let mut cache = cache_storage.cache::<CharCountCache<'_>>();
22/// assert_eq!(*cache.get("hello"), 5);
23/// ```
24#[derive(Default)]
25pub struct CacheStorage {
26    caches: ahash::HashMap<std::any::TypeId, Box<dyn CacheTrait>>,
27}
28
29impl CacheStorage {
30    pub fn cache<Cache: CacheTrait + Default>(&mut self) -> &mut Cache {
31        let cache = self
32            .caches
33            .entry(std::any::TypeId::of::<Cache>())
34            .or_insert_with(|| Box::<Cache>::default());
35
36        #[expect(clippy::unwrap_used)]
37        (cache.as_mut() as &mut dyn std::any::Any)
38            .downcast_mut::<Cache>()
39            .unwrap()
40    }
41
42    /// Total number of cached values
43    fn num_values(&self) -> usize {
44        self.caches.values().map(|cache| cache.len()).sum()
45    }
46
47    /// Call once per frame to evict cache.
48    pub fn update(&mut self) {
49        self.caches.retain(|_, cache| {
50            cache.update();
51            cache.len() > 0
52        });
53    }
54}
55
56impl Clone for CacheStorage {
57    fn clone(&self) -> Self {
58        // We return an empty cache that can be filled in again.
59        Self::default()
60    }
61}
62
63impl std::fmt::Debug for CacheStorage {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        write!(
66            f,
67            "FrameCacheStorage[{} caches with {} elements]",
68            self.caches.len(),
69            self.num_values()
70        )
71    }
72}