#[cfg(feature = "heapsize")]
extern crate heapsize_;
use std::borrow::Borrow;
use std::fmt;
use std::hash::BuildHasher;
use std::hash::Hash;
use ritelinked::linked_hash_map;
use ritelinked::DefaultHashBuilder;
use ritelinked::LinkedHashMap;
use crate::cache::Cache;
use crate::meter::count_meter::Count;
use crate::meter::count_meter::CountableMeter;
#[derive(Clone)]
pub struct LruCache<
K: Eq + Hash,
V,
S: BuildHasher = DefaultHashBuilder,
M: CountableMeter<K, V> = Count,
> {
map: LinkedHashMap<K, V, S>,
current_measure: M::Measure,
max_capacity: u64,
meter: M,
}
impl<K: Eq + Hash, V> LruCache<K, V> {
pub fn new(capacity: u64) -> Self {
LruCache {
map: LinkedHashMap::new(),
current_measure: (),
max_capacity: capacity,
meter: Count,
}
}
}
impl<K: Eq + Hash, V, M: CountableMeter<K, V>> LruCache<K, V, DefaultHashBuilder, M> {
pub fn with_meter(capacity: u64, meter: M) -> LruCache<K, V, DefaultHashBuilder, M> {
LruCache {
map: LinkedHashMap::new(),
current_measure: Default::default(),
max_capacity: capacity,
meter,
}
}
}
impl<K: Eq + Hash, V, S: BuildHasher> LruCache<K, V, S, Count> {
pub fn with_hasher(capacity: u64, hash_builder: S) -> LruCache<K, V, S, Count> {
LruCache {
map: LinkedHashMap::with_hasher(hash_builder),
current_measure: (),
max_capacity: capacity,
meter: Count,
}
}
}
impl<K: Eq + Hash, V, S: BuildHasher, M: CountableMeter<K, V>> Cache<K, V, S, M>
for LruCache<K, V, S, M>
{
fn with_meter_and_hasher(capacity: u64, meter: M, hash_builder: S) -> Self {
LruCache {
map: LinkedHashMap::with_hasher(hash_builder),
current_measure: Default::default(),
max_capacity: capacity,
meter,
}
}
fn get<Q>(&mut self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.map.get_refresh(k).map(|v| v as &V)
}
fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.map.get_refresh(k)
}
fn peek<'a, Q>(&'a self, k: &Q) -> Option<&'a V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.map.get(k)
}
fn peek_mut<'a, Q>(&'a mut self, k: &Q) -> Option<&'a mut V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.map.get_mut(k)
}
fn peek_by_policy(&self) -> Option<(&K, &V)> {
self.map.front()
}
fn contains<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.map.contains_key(key)
}
fn put(&mut self, k: K, v: V) -> Option<V> {
let new_size = self.meter.measure(&k, &v);
self.current_measure = self.meter.add(self.current_measure, new_size);
if let Some(old) = self.map.get(&k) {
self.current_measure =
self.meter.sub(self.current_measure, self.meter.measure(&k, old));
}
let old_val = self.map.insert(k, v);
while self.size() > self.capacity() {
self.pop_by_policy();
}
old_val
}
fn pop<Q>(&mut self, k: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.map.remove(k).map(|v| {
self.current_measure = self.meter.sub(self.current_measure, self.meter.measure(k, &v));
v
})
}
#[inline]
fn pop_by_policy(&mut self) -> Option<(K, V)> {
self.map.pop_front().map(|(k, v)| {
self.current_measure = self.meter.sub(self.current_measure, self.meter.measure(&k, &v));
(k, v)
})
}
fn set_capacity(&mut self, capacity: u64) {
while self.size() > capacity {
self.pop_by_policy();
}
self.max_capacity = capacity;
}
fn len(&self) -> usize {
self.map.len()
}
fn size(&self) -> u64 {
self.meter.size(self.current_measure).unwrap_or_else(|| self.map.len() as u64)
}
fn capacity(&self) -> u64 {
self.max_capacity
}
fn is_empty(&self) -> bool {
self.map.is_empty()
}
fn clear(&mut self) {
self.map.clear();
self.current_measure = Default::default();
}
}
impl<K: Eq + Hash, V, S: BuildHasher, M: CountableMeter<K, V>> LruCache<K, V, S, M> {
pub fn iter(&self) -> Iter<'_, K, V> {
Iter(self.map.iter())
}
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
IterMut(self.map.iter_mut())
}
}
impl<K: Eq + Hash, V, S: BuildHasher, M: CountableMeter<K, V>> Extend<(K, V)>
for LruCache<K, V, S, M>
{
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
for (k, v) in iter {
self.put(k, v);
}
}
}
impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher, M: CountableMeter<K, V>> fmt::Debug
for LruCache<K, V, S, M>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter().rev()).finish()
}
}
impl<K: Eq + Hash, V, S: BuildHasher, M: CountableMeter<K, V>> IntoIterator
for LruCache<K, V, S, M>
{
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
fn into_iter(self) -> IntoIter<K, V> {
IntoIter(self.map.into_iter())
}
}
impl<'a, K: Eq + Hash, V, S: BuildHasher, M: CountableMeter<K, V>> IntoIterator
for &'a LruCache<K, V, S, M>
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
fn into_iter(self) -> Iter<'a, K, V> {
self.iter()
}
}
impl<'a, K: Eq + Hash, V, S: BuildHasher, M: CountableMeter<K, V>> IntoIterator
for &'a mut LruCache<K, V, S, M>
{
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
fn into_iter(self) -> IterMut<'a, K, V> {
self.iter_mut()
}
}
pub struct IntoIter<K, V>(linked_hash_map::IntoIter<K, V>);
impl<K, V> Iterator for IntoIter<K, V> {
type Item = (K, V);
fn next(&mut self) -> Option<(K, V)> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
fn next_back(&mut self) -> Option<(K, V)> {
self.0.next_back()
}
}
impl<K, V> ExactSizeIterator for IntoIter<K, V> {
fn len(&self) -> usize {
self.0.len()
}
}
pub struct Iter<'a, K, V>(linked_hash_map::Iter<'a, K, V>);
impl<'a, K, V> Clone for Iter<'a, K, V> {
fn clone(&self) -> Iter<'a, K, V> {
Iter(self.0.clone())
}
}
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<(&'a K, &'a V)> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
self.0.next_back()
}
}
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
fn len(&self) -> usize {
self.0.len()
}
}
pub struct IterMut<'a, K, V>(linked_hash_map::IterMut<'a, K, V>);
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
self.0.next_back()
}
}
impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
fn len(&self) -> usize {
self.0.len()
}
}