cached/stores/
mod.rs

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)]
140/// Cache store tests
141mod 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}