1use crate::Cached;
2use std::cmp::Eq;
3use std::collections::hash_map::Entry;
4use std::collections::HashMap;
5use std::hash::Hash;
6
7#[cfg(feature = "async")]
8use {super::CachedAsync, async_trait::async_trait, futures::Future};
9
10#[cfg(feature = "disk_store")]
11mod disk;
12mod expiring_sized;
13mod expiring_value_cache;
14#[cfg(feature = "redis_store")]
15mod redis;
16mod sized;
17mod timed;
18mod timed_sized;
19mod unbound;
20
21#[cfg(feature = "disk_store")]
22pub use crate::stores::disk::{DiskCache, DiskCacheBuildError, DiskCacheBuilder, DiskCacheError};
23#[cfg(feature = "redis_store")]
24#[cfg_attr(docsrs, doc(cfg(feature = "redis_store")))]
25pub use crate::stores::redis::{
26 RedisCache, RedisCacheBuildError, RedisCacheBuilder, RedisCacheError,
27};
28pub use expiring_sized::ExpiringSizedCache;
29pub use expiring_value_cache::{CanExpire, ExpiringValueCache};
30pub use sized::SizedCache;
31pub use timed::TimedCache;
32pub use timed_sized::TimedSizedCache;
33pub use unbound::UnboundCache;
34
35#[cfg(all(
36 feature = "async",
37 feature = "redis_store",
38 any(feature = "redis_async_std", feature = "redis_tokio")
39))]
40#[cfg_attr(
41 docsrs,
42 doc(cfg(all(
43 feature = "async",
44 feature = "redis_store",
45 any(feature = "redis_async_std", feature = "redis_tokio")
46 )))
47)]
48pub use crate::stores::redis::{AsyncRedisCache, AsyncRedisCacheBuilder};
49
50impl<K, V, S> Cached<K, V> for HashMap<K, V, S>
51where
52 K: Hash + Eq,
53 S: std::hash::BuildHasher + Default,
54{
55 fn cache_get<Q>(&mut self, k: &Q) -> Option<&V>
56 where
57 K: std::borrow::Borrow<Q>,
58 Q: std::hash::Hash + Eq + ?Sized,
59 {
60 self.get(k)
61 }
62 fn cache_get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
63 where
64 K: std::borrow::Borrow<Q>,
65 Q: std::hash::Hash + Eq + ?Sized,
66 {
67 self.get_mut(k)
68 }
69 fn cache_set(&mut self, k: K, v: V) -> Option<V> {
70 self.insert(k, v)
71 }
72 fn cache_get_or_set_with<F: FnOnce() -> V>(&mut self, key: K, f: F) -> &mut V {
73 self.entry(key).or_insert_with(f)
74 }
75 fn cache_try_get_or_set_with<F: FnOnce() -> Result<V, E>, E>(
76 &mut self,
77 k: K,
78 f: F,
79 ) -> Result<&mut V, E> {
80 let v = match self.entry(k) {
81 Entry::Occupied(occupied) => occupied.into_mut(),
82 Entry::Vacant(vacant) => vacant.insert(f()?),
83 };
84
85 Ok(v)
86 }
87 fn cache_remove<Q>(&mut self, k: &Q) -> Option<V>
88 where
89 K: std::borrow::Borrow<Q>,
90 Q: std::hash::Hash + Eq + ?Sized,
91 {
92 self.remove(k)
93 }
94 fn cache_clear(&mut self) {
95 self.clear();
96 }
97 fn cache_reset(&mut self) {
98 *self = HashMap::default();
99 }
100 fn cache_size(&self) -> usize {
101 self.len()
102 }
103}
104
105#[cfg(feature = "async")]
106#[async_trait]
107impl<K, V, S> CachedAsync<K, V> for HashMap<K, V, S>
108where
109 K: Hash + Eq + Clone + Send,
110 S: std::hash::BuildHasher + Send,
111{
112 async fn get_or_set_with<F, Fut>(&mut self, k: K, f: F) -> &mut V
113 where
114 V: Send,
115 F: FnOnce() -> Fut + Send,
116 Fut: Future<Output = V> + Send,
117 {
118 match self.entry(k) {
119 Entry::Occupied(o) => o.into_mut(),
120 Entry::Vacant(v) => v.insert(f().await),
121 }
122 }
123
124 async fn try_get_or_set_with<F, Fut, E>(&mut self, k: K, f: F) -> Result<&mut V, E>
125 where
126 V: Send,
127 F: FnOnce() -> Fut + Send,
128 Fut: Future<Output = Result<V, E>> + Send,
129 {
130 let v = match self.entry(k) {
131 Entry::Occupied(o) => o.into_mut(),
132 Entry::Vacant(v) => v.insert(f().await?),
133 };
134
135 Ok(v)
136 }
137}
138
139#[cfg(test)]
140mod tests {
142 use super::*;
143
144 #[test]
145 fn hashmap() {
146 let mut c = std::collections::HashMap::new();
147 assert!(c.cache_get(&1).is_none());
148 assert_eq!(c.cache_misses(), None);
149
150 assert_eq!(c.cache_set(1, 100), None);
151 assert_eq!(c.cache_get(&1), Some(&100));
152 assert_eq!(c.cache_hits(), None);
153 assert_eq!(c.cache_misses(), None);
154 }
155}