#[cfg(not(feature = "asynchronous"))]
use std::rc::Rc;
#[cfg(feature = "asynchronous")]
use std::sync::Arc;
use std::{borrow::Borrow, collections::HashMap, hash::Hash};
use storage::{Pointer, Storage};
#[cfg(feature = "asynchronous")]
pub(crate) mod asynchronous;
mod storage;
#[cfg(test)]
mod tests;
#[cfg(not(feature = "asynchronous"))]
type Ref<T> = Rc<T>;
#[cfg(feature = "asynchronous")]
type Ref<T> = Arc<T>;
pub struct Cache<K, V> {
storage: Storage<Ref<K>, V>,
map: HashMap<Ref<K>, Pointer>,
}
impl<K: Hash + Eq, V> Cache<K, V> {
pub fn new(multiply_cap: usize, timeout_secs: u64) -> Self {
if multiply_cap == 0 {
panic!("Cache defined with 0 capacity")
}
Cache {
storage: Storage::new(multiply_cap, timeout_secs),
map: HashMap::with_capacity(multiply_cap),
}
}
pub fn get<Q: ?Sized>(&mut self, key: &Q) -> Option<&V>
where
Ref<K>: Borrow<Q>,
Q: Hash + Eq,
{
if self.map.is_empty() {
None
} else if let Some(&index) = self.map.get(key) {
let result = self.storage.get(index);
if result.is_none() {
self.map.remove(key);
}
result
} else {
None
}
}
pub fn put(&mut self, key: K, value: V) -> Option<V> {
if let Some(&index) = self.map.get(&key) {
Some(self.storage.update(index, value))
} else {
let key = Ref::new(key);
let (idx, old_pair) = self.storage.put(key.clone(), value);
let result = if let Some((old_key, old_data)) = old_pair {
self.map.remove(&old_key);
Some(old_data)
} else {
None
};
self.map.insert(key, idx);
result
}
}
pub fn evict(&mut self) {
if !self.is_empty() {
self.storage.evict().drain(..).for_each(|key| {
self.map.remove(&key);
})
}
}
pub fn capacity(&self) -> usize {
self.storage.capacity()
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
}