Skip to main content

LruCache

Struct LruCache 

Source
pub struct LruCache<K, V, S = DefaultHashBuilder> { /* private fields */ }
Expand description

A Least Recently Used (LRU) cache with O(1) operations.

Maintains items in order of access recency. When capacity is reached, the least recently accessed item is evicted to make room for new entries.

§Type Parameters

  • K: Key type. Must implement Hash + Eq. For mutation operations, also needs Clone.
  • V: Value type. Must implement Clone for retrieval operations.
  • S: Hash builder type. Defaults to DefaultHashBuilder.

§Capacity Modes

  • Count-based: LruCache::new(cap) - limits number of entries
  • Size-based: LruCache::init(config, None) with max_size set - limits total content size
  • Dual-limit: LruCache::with_limits(cap, bytes) - limits both

§Example

use cache_rs::LruCache;
use cache_rs::config::LruCacheConfig;
use core::num::NonZeroUsize;

let config = LruCacheConfig {
    capacity: NonZeroUsize::new(2).unwrap(),
    max_size: u64::MAX,
};
let mut cache = LruCache::init(config, None);

cache.put("apple", 1, 1);
cache.put("banana", 2, 1);
assert_eq!(cache.get(&"apple"), Some(&1));

// "banana" is now LRU, so it gets evicted
cache.put("cherry", 3, 1);
assert_eq!(cache.get(&"banana"), None);

Implementations§

Source§

impl<K: Hash + Eq, V: Clone, S: BuildHasher> LruCache<K, V, S>

Source

pub fn cap(&self) -> NonZeroUsize

Returns the maximum number of entries the cache can hold.

Source

pub fn len(&self) -> usize

Returns the current number of entries in the cache.

Source

pub fn is_empty(&self) -> bool

Returns true if the cache contains no entries.

Source

pub fn current_size(&self) -> u64

Returns the current total size of all cached content.

This is the sum of all size values passed to put(), or estimated sizes for entries added via put().

Source

pub fn max_size(&self) -> u64

Returns the maximum total content size the cache can hold.

Returns u64::MAX if no size limit was configured.

Source

pub fn get<Q>(&mut self, key: &Q) -> Option<&V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq,

Retrieves a reference to the value for the given key.

If the key exists, it is moved to the most-recently-used (MRU) position. Returns None if the key is not present.

§Example
use cache_rs::LruCache;
use cache_rs::config::LruCacheConfig;
use core::num::NonZeroUsize;

let config = LruCacheConfig {
    capacity: NonZeroUsize::new(10).unwrap(),
    max_size: u64::MAX,
};
let mut cache = LruCache::init(config, None);
cache.put("key", 42, 1);

assert_eq!(cache.get(&"key"), Some(&42));
assert_eq!(cache.get(&"missing"), None);
Source

pub fn record_miss(&mut self, object_size: u64)

Records a cache miss for metrics tracking.

Call this when you look up a key, find it missing, and fetch from the underlying data source. This updates the miss counter in metrics.

§Arguments
  • object_size - Size of the object that was fetched (for byte tracking)
Source

pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq,

Retrieves a mutable reference to the value for the given key.

If the key exists, it is moved to the MRU position. Returns None if the key is not present.

§Example
use cache_rs::LruCache;
use cache_rs::config::LruCacheConfig;
use core::num::NonZeroUsize;

let config = LruCacheConfig {
    capacity: NonZeroUsize::new(10).unwrap(),
    max_size: u64::MAX,
};
let mut cache = LruCache::init(config, None);
cache.put("counter", 0, 1);

if let Some(val) = cache.get_mut(&"counter") {
    *val += 1;
}
assert_eq!(cache.get(&"counter"), Some(&1));
Source§

impl<K: Hash + Eq + Clone, V: Clone, S: BuildHasher> LruCache<K, V, S>

Source

pub fn put(&mut self, key: K, value: V, size: u64) -> Option<Vec<(K, V)>>

Inserts a key-value pair into the cache.

If the key already exists, the value is updated and the entry moves to the MRU position.

If the cache is at capacity, evicted entries are returned.

§Returns
  • Some(vec) containing evicted entries (not replaced entries)
  • None if no entries were evicted (zero allocation)
§Arguments
  • key - The key to insert
  • value - The value to cache
  • size - Size of this entry for capacity tracking. Use SIZE_UNIT (1) for count-based caching.
§Example
use cache_rs::LruCache;
use cache_rs::config::LruCacheConfig;
use core::num::NonZeroUsize;

let config = LruCacheConfig {
    capacity: NonZeroUsize::new(2).unwrap(),
    max_size: u64::MAX,
};
let mut cache = LruCache::init(config, None);

// Count-based caching (use 1 for size)
assert_eq!(cache.put("a", 1, 1), None);                     // New entry
assert_eq!(cache.put("b", 2, 1), None);                     // New entry
assert_eq!(cache.put("a", 10, 1), None);                    // Update existing (not eviction)
assert_eq!(cache.put("c", 3, 1), Some(vec![("b", 2)]));     // Evicts "b"

Size-aware caching:

use cache_rs::LruCache;
use cache_rs::config::LruCacheConfig;
use core::num::NonZeroUsize;

let config = LruCacheConfig {
    capacity: NonZeroUsize::new(100).unwrap(),
    max_size: 1024 * 1024,  // 1MB max
};
let mut cache: LruCache<String, Vec<u8>> = LruCache::init(config, None);

let data = vec![0u8; 1000];
cache.put("file".to_string(), data, 1000);

assert_eq!(cache.current_size(), 1000);
Source

pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq,

Removes a key from the cache.

Returns the value if the key was present, None otherwise.

§Example
use cache_rs::LruCache;
use cache_rs::config::LruCacheConfig;
use core::num::NonZeroUsize;

let config = LruCacheConfig {
    capacity: NonZeroUsize::new(10).unwrap(),
    max_size: u64::MAX,
};
let mut cache = LruCache::init(config, None);
cache.put("key", 42, 1);

assert_eq!(cache.remove(&"key"), Some(42));
assert_eq!(cache.remove(&"key"), None);  // Already removed
Source

pub fn clear(&mut self)

Removes all entries from the cache.

Resets current_size to 0 and clears all metrics counters.

Source

pub fn contains<Q>(&self, key: &Q) -> bool
where K: Borrow<Q>, Q: ?Sized + Hash + Eq,

Check if key exists without promoting it in the LRU order.

Unlike get(), this method does NOT update the entry’s access time or move it to the front of the list. Useful for existence checks without affecting cache eviction order.

§Example
use cache_rs::LruCache;
use cache_rs::config::LruCacheConfig;
use core::num::NonZeroUsize;

let config = LruCacheConfig {
    capacity: NonZeroUsize::new(2).unwrap(),
    max_size: u64::MAX,
};
let mut cache = LruCache::init(config, None);
cache.put("a", 1, 1);
cache.put("b", 2, 1);

// contains() does NOT promote "a"
assert!(cache.contains(&"a"));

// "a" is still LRU, so adding "c" evicts "a"
cache.put("c", 3, 1);
assert!(!cache.contains(&"a"));
Source

pub fn peek<Q>(&self, key: &Q) -> Option<&V>
where K: Borrow<Q>, Q: ?Sized + Hash + Eq,

Returns a reference to the value without updating the LRU order.

Unlike get(), this does NOT move the entry to the front of the list or update any access metadata.

§Example
use cache_rs::LruCache;
use cache_rs::config::LruCacheConfig;
use core::num::NonZeroUsize;

let config = LruCacheConfig {
    capacity: NonZeroUsize::new(3).unwrap(),
    max_size: u64::MAX,
};
let mut cache = LruCache::init(config, None);
cache.put("a", 1, 1);
cache.put("b", 2, 1);

// peek does not change LRU ordering
assert_eq!(cache.peek(&"a"), Some(&1));
assert_eq!(cache.peek(&"missing"), None);
Source

pub fn iter(&self) -> Iter<'_, K, V>

Returns an iterator over the cache entries.

§Panics

Not yet implemented.

Source

pub fn iter_mut(&mut self) -> IterMut<'_, K, V>

Returns a mutable iterator over the cache entries.

§Panics

Not yet implemented.

Source§

impl<K: Hash + Eq, V> LruCache<K, V>
where V: Clone,

Source

pub fn init( config: LruCacheConfig, hasher: Option<DefaultHashBuilder>, ) -> LruCache<K, V, DefaultHashBuilder>

Creates a new LRU cache from a configuration with an optional hasher.

This is the only way to create an LRU cache.

§Arguments
  • config - Configuration specifying capacity and optional size limit
  • hasher - Optional custom hash builder. If None, uses DefaultHashBuilder
§Example
use cache_rs::LruCache;
use cache_rs::config::LruCacheConfig;
use core::num::NonZeroUsize;

// Simple capacity-only cache
let config = LruCacheConfig {
    capacity: NonZeroUsize::new(100).unwrap(),
    max_size: u64::MAX,
};
let mut cache: LruCache<&str, i32> = LruCache::init(config, None);
cache.put("key", 42, 1);

// Cache with size limit
let config = LruCacheConfig {
    capacity: NonZeroUsize::new(1000).unwrap(),
    max_size: 10 * 1024 * 1024,  // 10MB
};
let cache: LruCache<String, Vec<u8>> = LruCache::init(config, None);

Trait Implementations§

Source§

impl<K: Hash + Eq, V: Clone, S: BuildHasher> CacheMetrics for LruCache<K, V, S>

Source§

fn metrics(&self) -> BTreeMap<String, f64>

Returns all metrics as key-value pairs in deterministic order Read more
Source§

fn algorithm_name(&self) -> &'static str

Algorithm name for identification Read more
Source§

impl<K: Debug, V: Debug, S: Debug> Debug for LruCache<K, V, S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<K, V, S> Freeze for LruCache<K, V, S>
where S: Freeze,

§

impl<K, V, S> RefUnwindSafe for LruCache<K, V, S>

§

impl<K, V, S> Send for LruCache<K, V, S>
where K: Send, V: Send, S: Send,

§

impl<K, V, S> Sync for LruCache<K, V, S>
where K: Send, V: Send, S: Sync,

§

impl<K, V, S> Unpin for LruCache<K, V, S>
where S: Unpin, K: Unpin,

§

impl<K, V, S> UnsafeUnpin for LruCache<K, V, S>
where S: UnsafeUnpin,

§

impl<K, V, S> UnwindSafe for LruCache<K, V, S>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.