mini_moka/unsync/
builder.rs1use super::{Cache, Weigher};
2use crate::common::builder_utils;
3
4use std::{
5 collections::hash_map::RandomState,
6 hash::{BuildHasher, Hash},
7 marker::PhantomData,
8 time::Duration,
9};
10
11#[must_use]
42pub struct CacheBuilder<K, V, C> {
43 max_capacity: Option<u64>,
44 initial_capacity: Option<usize>,
45 weigher: Option<Weigher<K, V>>,
46 time_to_live: Option<Duration>,
47 time_to_idle: Option<Duration>,
48 cache_type: PhantomData<C>,
49}
50
51impl<K, V> Default for CacheBuilder<K, V, Cache<K, V, RandomState>>
52where
53 K: Eq + Hash,
54{
55 fn default() -> Self {
56 Self {
57 max_capacity: None,
58 initial_capacity: None,
59 weigher: None,
60 time_to_live: None,
61 time_to_idle: None,
62 cache_type: Default::default(),
63 }
64 }
65}
66
67impl<K, V> CacheBuilder<K, V, Cache<K, V, RandomState>>
68where
69 K: Eq + Hash,
70{
71 pub fn new(max_capacity: u64) -> Self {
74 Self {
75 max_capacity: Some(max_capacity),
76 ..Default::default()
77 }
78 }
79
80 pub fn build(self) -> Cache<K, V, RandomState> {
88 let build_hasher = RandomState::default();
89 builder_utils::ensure_expirations_or_panic(self.time_to_live, self.time_to_idle);
90 Cache::with_everything(
91 self.max_capacity,
92 self.initial_capacity,
93 build_hasher,
94 self.weigher,
95 self.time_to_live,
96 self.time_to_idle,
97 )
98 }
99
100 pub fn build_with_hasher<S>(self, hasher: S) -> Cache<K, V, S>
108 where
109 S: BuildHasher + Clone,
110 {
111 builder_utils::ensure_expirations_or_panic(self.time_to_live, self.time_to_idle);
112 Cache::with_everything(
113 self.max_capacity,
114 self.initial_capacity,
115 hasher,
116 self.weigher,
117 self.time_to_live,
118 self.time_to_idle,
119 )
120 }
121}
122
123impl<K, V, C> CacheBuilder<K, V, C> {
124 pub fn max_capacity(self, max_capacity: u64) -> Self {
126 Self {
127 max_capacity: Some(max_capacity),
128 ..self
129 }
130 }
131
132 pub fn initial_capacity(self, number_of_entries: usize) -> Self {
134 Self {
135 initial_capacity: Some(number_of_entries),
136 ..self
137 }
138 }
139
140 pub fn weigher(self, weigher: impl FnMut(&K, &V) -> u32 + 'static) -> Self {
145 Self {
146 weigher: Some(Box::new(weigher)),
147 ..self
148 }
149 }
150
151 pub fn time_to_live(self, duration: Duration) -> Self {
162 Self {
163 time_to_live: Some(duration),
164 ..self
165 }
166 }
167
168 pub fn time_to_idle(self, duration: Duration) -> Self {
179 Self {
180 time_to_idle: Some(duration),
181 ..self
182 }
183 }
184}
185
186#[cfg(test)]
187mod tests {
188 use super::CacheBuilder;
189
190 use std::time::Duration;
191
192 #[test]
193 fn build_cache() {
194 let mut cache = CacheBuilder::new(100).build();
196 let policy = cache.policy();
197
198 assert_eq!(policy.max_capacity(), Some(100));
199 assert_eq!(policy.time_to_live(), None);
200 assert_eq!(policy.time_to_idle(), None);
201
202 cache.insert('a', "Alice");
203 assert_eq!(cache.get(&'a'), Some(&"Alice"));
204
205 let mut cache = CacheBuilder::new(100)
206 .time_to_live(Duration::from_secs(45 * 60))
207 .time_to_idle(Duration::from_secs(15 * 60))
208 .build();
209 let policy = cache.policy();
210
211 assert_eq!(policy.max_capacity(), Some(100));
212 assert_eq!(policy.time_to_live(), Some(Duration::from_secs(45 * 60)));
213 assert_eq!(policy.time_to_idle(), Some(Duration::from_secs(15 * 60)));
214
215 cache.insert('a', "Alice");
216 assert_eq!(cache.get(&'a'), Some(&"Alice"));
217 }
218
219 #[test]
220 #[should_panic(expected = "time_to_live is longer than 1000 years")]
221 fn build_cache_too_long_ttl() {
222 let thousand_years_secs: u64 = 1000 * 365 * 24 * 3600;
223 let builder: CacheBuilder<char, String, _> = CacheBuilder::new(100);
224 let duration = Duration::from_secs(thousand_years_secs);
225 builder
226 .time_to_live(duration + Duration::from_secs(1))
227 .build();
228 }
229
230 #[test]
231 #[should_panic(expected = "time_to_idle is longer than 1000 years")]
232 fn build_cache_too_long_tti() {
233 let thousand_years_secs: u64 = 1000 * 365 * 24 * 3600;
234 let builder: CacheBuilder<char, String, _> = CacheBuilder::new(100);
235 let duration = Duration::from_secs(thousand_years_secs);
236 builder
237 .time_to_idle(duration + Duration::from_secs(1))
238 .build();
239 }
240}