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}