Skip to main content

lgui_core/memory/
options.rs

1use super::ImageCachePolicy;
2
3const DEFAULT_CACHE_BYTES: usize = 64 * 1024 * 1024;
4
5/// Application memory budget.
6///
7/// A single `cache_bytes` ceiling is applied to every framework-owned cache
8/// (renderer raster/text cache, decoded-image cache, scroll-raster command
9/// cache, and so on). Each cache independently evicts its own entries to stay
10/// within this ceiling, so total resident memory is bounded by the number of
11/// live caches times `cache_bytes`.
12#[cfg_attr(feature = "diagnostics-serde", derive(serde::Serialize))]
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub struct MemoryBudget {
15    pub cache_bytes: usize,
16    /// Persistent store quota; only meaningful with the `persistent-cache`
17    /// feature.
18    pub persistent_bytes: u64,
19}
20
21impl MemoryBudget {
22    pub const fn new(cache_bytes: usize) -> Self {
23        Self {
24            cache_bytes,
25            persistent_bytes: 0,
26        }
27    }
28
29    pub const fn with_persistent(cache_bytes: usize, persistent_bytes: u64) -> Self {
30        Self {
31            cache_bytes,
32            persistent_bytes,
33        }
34    }
35}
36
37impl Default for MemoryBudget {
38    fn default() -> Self {
39        Self::new(DEFAULT_CACHE_BYTES)
40    }
41}
42
43/// Application-scoped memory policy.
44///
45/// The budget is the single user-facing knob; image cache policy and
46/// persistent-cache toggle are orthogonal behavior switches. When no policy is
47/// provided, [`MemoryOptions::default`] applies a 64 MiB per-cache budget with
48/// `WhileVisible` image caching.
49#[cfg_attr(feature = "diagnostics-serde", derive(serde::Serialize))]
50#[derive(Clone, Copy, Debug, PartialEq, Eq)]
51pub struct MemoryOptions {
52    pub budget: MemoryBudget,
53    pub default_image_cache_policy: ImageCachePolicy,
54    pub persistent_cache_enabled: bool,
55}
56
57impl MemoryOptions {
58    pub const fn new(
59        budget: MemoryBudget,
60        default_image_cache_policy: ImageCachePolicy,
61        persistent_cache_enabled: bool,
62    ) -> Self {
63        Self {
64            budget,
65            default_image_cache_policy,
66            persistent_cache_enabled,
67        }
68    }
69
70    pub const fn cache_budget(cache_bytes: usize) -> Self {
71        Self::new(
72            MemoryBudget::new(cache_bytes),
73            ImageCachePolicy::WhileVisible,
74            false,
75        )
76    }
77
78    pub const fn unbounded(
79        default_image_cache_policy: ImageCachePolicy,
80        persistent_cache_enabled: bool,
81    ) -> Self {
82        Self::new(
83            MemoryBudget {
84                cache_bytes: usize::MAX,
85                persistent_bytes: u64::MAX,
86            },
87            default_image_cache_policy,
88            persistent_cache_enabled,
89        )
90    }
91
92    pub const fn persistent_cache(mut self, enabled: bool) -> Self {
93        self.persistent_cache_enabled = enabled;
94        self
95    }
96
97    pub const fn persistent_budget(mut self, bytes: u64) -> Self {
98        self.budget.persistent_bytes = bytes;
99        self
100    }
101
102    pub fn validate(self) -> Result<(), &'static str> {
103        if self.default_image_cache_policy == ImageCachePolicy::ApplicationDefault {
104            return Err("application default image policy must be concrete");
105        }
106        Ok(())
107    }
108}
109
110impl Default for MemoryOptions {
111    fn default() -> Self {
112        Self::cache_budget(DEFAULT_CACHE_BYTES)
113    }
114}