cache_rs/config/
slru.rs

1//! Configuration for the Segmented Least Recently Used (SLRU) cache.
2
3use core::fmt;
4use core::num::NonZeroUsize;
5
6/// Configuration for an SLRU (Segmented LRU) cache.
7///
8/// SLRU divides the cache into two segments: a probationary segment for new entries
9/// and a protected segment for frequently accessed entries.
10///
11/// # Examples
12///
13/// ```
14/// use cache_rs::config::slru::SlruCacheConfig;
15/// use core::num::NonZeroUsize;
16///
17/// // Create a config with total capacity of 4 items and protected capacity of 2 items
18/// let config = SlruCacheConfig::new(
19///     NonZeroUsize::new(4).unwrap(),
20///     NonZeroUsize::new(2).unwrap()
21/// );
22///
23/// assert_eq!(config.capacity(), NonZeroUsize::new(4).unwrap());
24/// assert_eq!(config.protected_capacity(), NonZeroUsize::new(2).unwrap());
25/// ```
26#[derive(Clone, Copy)]
27pub struct SlruCacheConfig {
28    /// Total capacity of the cache (protected + probationary)
29    capacity: NonZeroUsize,
30
31    /// Maximum size for the protected segment
32    protected_capacity: NonZeroUsize,
33}
34
35impl SlruCacheConfig {
36    /// Creates a new configuration for an SLRU cache.
37    ///
38    /// # Arguments
39    /// * `capacity` - Total number of key-value pairs the cache can hold
40    /// * `protected_capacity` - Maximum size of the protected segment
41    ///
42    /// # Panics
43    /// Panics if `protected_capacity` is greater than `capacity`
44    pub fn new(capacity: NonZeroUsize, protected_capacity: NonZeroUsize) -> Self {
45        assert!(
46            protected_capacity.get() <= capacity.get(),
47            "Protected capacity must be less than or equal to total capacity"
48        );
49
50        Self {
51            capacity,
52            protected_capacity,
53        }
54    }
55
56    /// Returns the maximum number of key-value pairs the cache can hold.
57    pub fn capacity(&self) -> NonZeroUsize {
58        self.capacity
59    }
60
61    /// Returns the maximum size of the protected segment.
62    pub fn protected_capacity(&self) -> NonZeroUsize {
63        self.protected_capacity
64    }
65}
66
67impl fmt::Debug for SlruCacheConfig {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        f.debug_struct("SlruCacheConfig")
70            .field("capacity", &self.capacity)
71            .field("protected_capacity", &self.protected_capacity)
72            .finish()
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn test_slru_config_creation() {
82        let config = SlruCacheConfig::new(
83            NonZeroUsize::new(10).unwrap(),
84            NonZeroUsize::new(5).unwrap(),
85        );
86
87        assert_eq!(config.capacity().get(), 10);
88        assert_eq!(config.protected_capacity().get(), 5);
89    }
90
91    #[test]
92    #[should_panic(expected = "Protected capacity must be less than or equal to total capacity")]
93    fn test_invalid_protected_capacity() {
94        // This should panic because protected capacity is greater than total capacity
95        SlruCacheConfig::new(
96            NonZeroUsize::new(5).unwrap(),
97            NonZeroUsize::new(10).unwrap(),
98        );
99    }
100}