use std::borrow::Borrow;
use std::fmt;
use std::hash::BuildHasher;
use std::hash::Hash;
pub use hashbrown;
use hashbrown::hash_map::DefaultHashBuilder;
use hashlink::linked_hash_map;
use hashlink::linked_hash_map::RawEntryMut;
use linked_hash_map::LinkedHashMap;
use crate::cache_iter::IntoIter;
use crate::cache_iter::Iter;
use crate::cache_iter::IterMut;
use crate::meter::Count;
use crate::meter::Meter;
use crate::peek_mut::PeekMut;
mod cache_iter;
pub mod meter;
mod peek_mut;
#[derive(Clone)]
pub struct LruCache<K: Eq + Hash, V, S: BuildHasher = DefaultHashBuilder, M: Meter<K, V> = Count> {
map: LinkedHashMap<K, V, S>,
max_items: usize,
meter: M,
current_measure: M::Measure,
max_capacity: M::Measure,
}
impl<K: Eq + Hash, V> LruCache<K, V> {
pub fn new(max_items: usize) -> Self {
LruCache {
map: LinkedHashMap::new(),
max_items,
current_measure: 0,
max_capacity: max_items,
meter: Count,
}
}
}
impl<K: Eq + Hash, V, M: Meter<K, V>> LruCache<K, V, DefaultHashBuilder, M> {
pub fn with_meter(
max_items: usize,
capacity: M::Measure,
meter: M,
) -> LruCache<K, V, DefaultHashBuilder, M> {
LruCache {
map: LinkedHashMap::new(),
max_items,
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: usize, hash_builder: S) -> LruCache<K, V, S, Count> {
LruCache {
map: LinkedHashMap::with_hasher(hash_builder),
max_items: capacity,
current_measure: 0,
max_capacity: capacity,
meter: Count,
}
}
}
impl<K: Eq + Hash, V, S: BuildHasher, M: Meter<K, V>> LruCache<K, V, S, M> {
pub fn with_meter_and_hasher(
max_items: usize,
capacity: M::Measure,
meter: M,
hash_builder: S,
) -> Self {
LruCache {
map: LinkedHashMap::with_hasher(hash_builder),
max_items,
current_measure: Default::default(),
max_capacity: capacity,
meter,
}
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn max_items(&self) -> usize {
self.max_items
}
pub fn set_max_items(&mut self, max_items: usize) {
self.max_items = max_items;
self.evict_by_policy();
}
pub fn size(&self) -> M::Measure {
self.current_measure
}
pub fn capacity(&self) -> M::Measure {
self.max_capacity
}
pub fn set_capacity(&mut self, capacity: M::Measure) {
self.max_capacity = capacity;
self.evict_by_policy();
}
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.map.contains_key(key)
}
pub fn peek<Q: ?Sized>(&mut self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
match self.map.raw_entry_mut().from_key(k) {
RawEntryMut::Occupied(occupied) => Some(occupied.into_mut()),
RawEntryMut::Vacant(_) => None,
}
}
pub fn peek_mut<'a, Q: ?Sized>(&'a mut self, k: &'a Q) -> Option<PeekMut<'a, K, V, S, M>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let me = self as *mut Self;
match self.map.raw_entry_mut().from_key(k) {
RawEntryMut::Occupied(occupied) => {
let p = PeekMut::new(occupied, me);
Some(p)
}
RawEntryMut::Vacant(_) => None,
}
}
pub fn get<Q: ?Sized>(&mut self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
match self.map.raw_entry_mut().from_key(k) {
RawEntryMut::Occupied(mut occupied) => {
occupied.to_back();
Some(occupied.into_mut())
}
RawEntryMut::Vacant(_) => None,
}
}
pub fn get_mut<'a, Q: ?Sized>(&'a mut self, k: &'a Q) -> Option<PeekMut<'a, K, V, S, M>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let me = self as *mut Self;
match self.map.raw_entry_mut().from_key(k) {
RawEntryMut::Occupied(mut occupied) => {
occupied.to_back();
let p = PeekMut::new(occupied, me);
Some(p)
}
RawEntryMut::Vacant(_) => None,
}
}
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
self.measure_add(&k, &v);
let old_val = match self.map.raw_entry_mut().from_key(&k) {
RawEntryMut::Occupied(mut occupied) => {
occupied.to_back();
let old_val = occupied.replace_value(v);
self.measure_remove(&k, &old_val);
Some(old_val)
}
RawEntryMut::Vacant(vacant) => {
vacant.insert(k, v);
None
}
};
self.evict_by_policy();
old_val
}
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.map.remove(k).map(|v| {
self.measure_remove(k, &v);
v
})
}
#[inline]
pub fn remove_lru(&mut self) -> Option<(K, V)> {
self.map.pop_front().map(|(k, v)| {
self.measure_remove(&k, &v);
(k, v)
})
}
pub fn clear(&mut self) {
self.map.clear();
self.current_measure = Default::default();
}
pub fn iter(&self) -> Iter<'_, K, V> {
Iter(self.map.iter())
}
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
self.internal_iter_mut()
}
fn internal_iter_mut(&mut self) -> IterMut<'_, K, V> {
IterMut(self.map.iter_mut())
}
pub(crate) fn evict_by_policy(&mut self) {
while self.len() > self.max_items() {
self.remove_lru();
}
while self.size() > self.capacity() {
self.remove_lru();
}
}
pub(crate) fn measure_add<Q: ?Sized>(&mut self, k: &Q, v: &V) -> M::Measure
where
K: Borrow<Q>,
{
self.current_measure = self.current_measure + self.meter.measure(k, v);
self.current_measure
}
pub(crate) fn measure_remove<Q: ?Sized>(&mut self, k: &Q, v: &V) -> M::Measure
where
K: Borrow<Q>,
{
self.current_measure = self.current_measure - self.meter.measure(k, v);
self.current_measure
}
}
impl<K: Eq + Hash, V, S: BuildHasher, M: Meter<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.insert(k, v);
}
}
}
impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher, M: Meter<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: Meter<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: Meter<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: Meter<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.internal_iter_mut()
}
}
#[cfg(test)]
mod tests {
use std::borrow::Borrow;
use std::ops::Deref;
use super::LruCache;
use crate::meter::Meter;
#[test]
fn test_put_and_get() {
let mut cache = LruCache::new(2);
cache.insert(1, 10);
cache.insert(2, 20);
assert_eq!(cache.get_mut(&1).unwrap().deref(), &mut 10);
assert_eq!(cache.get_mut(&2).unwrap().deref(), &mut 20);
assert_eq!(cache.len(), 2);
assert_eq!(cache.size(), 2);
}
#[test]
fn test_put_update() {
let mut cache = LruCache::new(1);
cache.insert("1", 10);
cache.insert("1", 19);
assert_eq!(cache.get_mut("1").unwrap().deref(), &mut 19);
assert_eq!(cache.len(), 1);
}
#[test]
fn test_contains_key() {
let mut cache = LruCache::new(1);
cache.insert("1", 10);
assert!(cache.contains_key("1"));
}
#[test]
fn test_expire_lru() {
let mut cache = LruCache::new(2);
cache.insert("foo1", "bar1");
cache.insert("foo2", "bar2");
cache.insert("foo3", "bar3");
assert!(cache.get_mut("foo1").is_none());
cache.insert("foo2", "bar2update");
cache.insert("foo4", "bar4");
assert!(cache.get_mut("foo3").is_none());
}
#[test]
fn test_pop() {
let mut cache = LruCache::new(2);
cache.insert(1, 10);
cache.insert(2, 20);
assert_eq!(cache.len(), 2);
let opt1 = cache.remove(&1);
assert!(opt1.is_some());
assert_eq!(opt1.unwrap(), 10);
assert!(cache.get_mut(&1).is_none());
assert_eq!(cache.len(), 1);
}
#[test]
fn test_change_capacity() {
let mut cache = LruCache::new(2);
assert_eq!(cache.capacity(), 2);
cache.insert(1, 10);
cache.insert(2, 20);
cache.set_capacity(1);
assert!(cache.get_mut(&1).is_none());
assert_eq!(cache.capacity(), 1);
}
#[test]
fn test_debug() {
let mut cache = LruCache::new(3);
cache.insert(1, 10);
cache.insert(2, 20);
cache.insert(3, 30);
assert_eq!(format!("{:?}", cache), "{3: 30, 2: 20, 1: 10}");
cache.insert(2, 22);
assert_eq!(format!("{:?}", cache), "{2: 22, 3: 30, 1: 10}");
cache.insert(6, 60);
assert_eq!(format!("{:?}", cache), "{6: 60, 2: 22, 3: 30}");
cache.get_mut(&3);
assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60, 2: 22}");
cache.set_capacity(2);
assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60}");
}
#[test]
fn test_remove() {
let mut cache = LruCache::new(3);
cache.insert(1, 10);
cache.insert(2, 20);
cache.insert(3, 30);
cache.insert(4, 40);
cache.insert(5, 50);
cache.remove(&3);
cache.remove(&4);
assert!(cache.get_mut(&3).is_none());
assert!(cache.get_mut(&4).is_none());
cache.insert(6, 60);
cache.insert(7, 70);
cache.insert(8, 80);
assert!(cache.get_mut(&5).is_none());
assert_eq!(cache.get_mut(&6).unwrap().deref(), &mut 60);
assert_eq!(cache.get_mut(&7).unwrap().deref(), &mut 70);
assert_eq!(cache.get_mut(&8).unwrap().deref(), &mut 80);
}
#[test]
fn test_get_mut_debug() {
let mut cache = LruCache::new(2);
cache.insert(1, 10);
let a = cache.get_mut(&1).unwrap();
assert_eq!("PeekMut(10)", format!("{:?}", a))
}
#[test]
fn test_get_mut_evict() {
let mut cache = LruCache::with_meter(2, 5, VecLen);
cache.insert(1, b"12".to_vec());
cache.insert(2, b"34".to_vec());
assert_eq!(cache.len(), 2);
{
let mut a = cache.get_mut(&1).unwrap();
*a = b"1234".to_vec();
}
assert_eq!(cache.len(), 1);
assert_eq!(cache.get(&1).unwrap(), &b"1234".to_vec());
{
let mut a = cache.get_mut(&1).unwrap();
*a = b"123456".to_vec();
}
assert_eq!(cache.len(), 0);
}
#[test]
fn test_peek() {
let mut cache = LruCache::with_meter(2, 5, VecLen);
cache.insert(1, b"12".to_vec());
cache.insert(2, b"34".to_vec());
assert_eq!(cache.peek(&1).unwrap(), &b"12".to_vec());
cache.insert(3, b"33".to_vec());
assert_eq!(cache.peek(&1), None);
}
#[test]
fn test_peek_mut() {
let mut cache = LruCache::with_meter(2, 5, VecLen);
cache.insert(1, b"12".to_vec());
cache.insert(2, b"34".to_vec());
{
let mut a = cache.peek_mut(&1).unwrap();
*a = b"56".to_vec();
}
assert_eq!(cache.peek(&1).unwrap(), &b"56".to_vec());
cache.insert(3, b"33".to_vec());
assert_eq!(cache.peek(&1), None);
}
#[test]
fn test_peek_mut_evict() {
let mut cache = LruCache::with_meter(2, 5, VecLen);
cache.insert(1, b"12".to_vec());
cache.insert(2, b"34".to_vec());
assert_eq!(cache.len(), 2);
{
let mut a = cache.peek_mut(&1).unwrap();
*a = b"1234".to_vec();
}
assert_eq!(cache.len(), 1);
assert_eq!(cache.get(&1), None);
assert_eq!(cache.get(&2).unwrap(), &b"34".to_vec());
}
#[test]
fn test_clear() {
let mut cache = LruCache::new(2);
cache.insert(1, 10);
cache.insert(2, 20);
cache.clear();
assert!(cache.get_mut(&1).is_none());
assert!(cache.get_mut(&2).is_none());
assert_eq!(format!("{:?}", cache), "{}");
}
#[test]
fn test_iter() {
let mut cache = LruCache::new(3);
cache.insert(1, 10);
cache.insert(2, 20);
cache.insert(3, 30);
cache.insert(4, 40);
cache.insert(5, 50);
assert_eq!(cache.iter().collect::<Vec<_>>(), [
(&3, &30),
(&4, &40),
(&5, &50)
]);
assert_eq!(cache.iter_mut().collect::<Vec<_>>(), [
(&3, &mut 30),
(&4, &mut 40),
(&5, &mut 50)
]);
assert_eq!(cache.iter().rev().collect::<Vec<_>>(), [
(&5, &50),
(&4, &40),
(&3, &30)
]);
assert_eq!(cache.iter_mut().rev().collect::<Vec<_>>(), [
(&5, &mut 50),
(&4, &mut 40),
(&3, &mut 30)
]);
}
struct VecLen;
impl<K, T> Meter<K, Vec<T>> for VecLen {
type Measure = usize;
fn measure<Q: ?Sized>(&self, _: &Q, v: &Vec<T>) -> usize
where
K: Borrow<Q>,
{
v.len()
}
}
#[test]
fn test_metered_cache() {
let mut cache = LruCache::with_meter(100, 5, VecLen);
cache.insert("foo1", vec![1, 2]);
assert_eq!(cache.size(), 2);
cache.insert("foo2", vec![3, 4]);
cache.insert("foo3", vec![5, 6]);
assert_eq!(cache.size(), 4);
assert!(!cache.contains_key("foo1"));
cache.insert("foo2", vec![7, 8]);
cache.insert("foo4", vec![9, 10]);
assert_eq!(cache.size(), 4);
assert!(!cache.contains_key("foo3"));
assert_eq!(cache.get("foo2"), Some(&vec![7, 8]));
}
#[test]
fn test_metered_cache_reinsert_larger_capacity() {
let mut cache = LruCache::with_meter(100, 5, VecLen);
cache.insert("foo1", vec![1, 2]);
cache.insert("foo2", vec![3, 4]);
assert_eq!(cache.size(), 4);
cache.insert("foo2", vec![5, 6, 7, 8]);
assert_eq!(cache.size(), 4);
assert!(!cache.contains_key("foo1"));
}
#[test]
fn test_metered_cache_reinsert_larger_max_items() {
let mut cache = LruCache::with_meter(2, 100, VecLen);
cache.insert("foo1", vec![1, 2]);
cache.insert("foo2", vec![3, 4]);
assert_eq!(cache.len(), 2);
cache.insert("foo2", vec![5, 6, 7, 8]);
assert_eq!(cache.len(), 2);
assert!(cache.contains_key("foo1"));
cache.insert("foo3", vec![9, 10]);
assert_eq!(cache.len(), 2);
assert!(!cache.contains_key("foo1"));
}
#[test]
fn test_metered_cache_oversize() {
let mut cache = LruCache::with_meter(100, 2, VecLen);
cache.insert("foo1", vec![1, 2]);
cache.insert("foo2", vec![3, 4, 5, 6]);
assert_eq!(cache.size(), 0);
assert!(!cache.contains_key("foo1"));
assert!(!cache.contains_key("foo2"));
}
#[test]
fn test_metered_cache_over_max_items() {
let mut cache = LruCache::with_meter(1, 100, VecLen);
cache.insert("foo1", vec![1, 2]);
cache.insert("foo2", vec![3, 4, 5, 6]);
assert_eq!(cache.len(), 1);
assert!(!cache.contains_key("foo1"));
assert!(cache.contains_key("foo2"));
}
}