SimpleCacher

Struct SimpleCacher 

Source
pub struct SimpleCacher<T, U> { /* private fields */ }
Expand description

A high-performance cache with automatic expiration and custom matching capabilities.

SimpleCacher provides fast O(1) exact key lookups using an IndexMap, along with flexible O(n) pattern matching via the Matcher trait. Entries automatically expire based on configurable TTL values, and the cache can be size-limited with FIFO eviction.

§Type Parameters

  • T - The type of keys (must implement Clone + Eq + Hash)
  • U - The type of cached values

§Examples

§Basic Usage

use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));

// Insert a value
cache.insert("user:123".to_string(), "Alice Johnson".to_string());

// Retrieve it
match cache.get(&"user:123".to_string()) {
    Ok(entry) => println!("Found: {}", entry.value()),
    Err(SimpleCacheError::NotFound) => println!("Not found"),
    Err(SimpleCacheError::Expired) => println!("Expired and removed"),
}

§Size-Limited Cache

use simple_cacher::*;
use std::time::Duration;

// Cache with max 1000 entries
let mut cache = SimpleCacher::with_max_size(Duration::from_secs(300), 1000);

// When full, oldest entries are automatically removed
for i in 0..1500 {
    cache.insert(format!("key_{}", i), format!("value_{}", i));
}

assert_eq!(cache.len(), 1000); // Only newest 1000 entries remain

Implementations§

Source§

impl<T, U> SimpleCacher<T, U>
where T: Clone + Eq + Hash,

Source

pub fn new(max_age: Duration) -> Self

Creates a new cache with the specified maximum age for entries.

All entries inserted into this cache will expire after the given duration, unless overridden with insert_with_ttl.

§Arguments
  • max_age - Default time-to-live for cache entries
§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300)); // 5 minutes
cache.insert("key".to_string(), "value".to_string());
Source

pub fn with_max_size(max_age: Duration, max_size: usize) -> Self

Creates a new cache with both maximum age and maximum size constraints.

When the cache exceeds max_size entries, the oldest entries are automatically removed to make room for new ones (FIFO eviction policy).

§Arguments
  • max_age - Default time-to-live for cache entries
  • max_size - Maximum number of entries to keep in the cache
§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache: SimpleCacher<String,String> = SimpleCacher::with_max_size(
    Duration::from_secs(300), // 5 minutes TTL
    1000 // max 1000 entries
);
Source

pub fn get( &mut self, key: &T, ) -> Result<&SimpleCacheObject<U>, SimpleCacheError>

Retrieves an entry by exact key match in O(1) time.

If the entry exists but has expired, it will be automatically removed from the cache and SimpleCacheError::Expired will be returned.

§Arguments
  • key - The key to look up
§Returns
  • Ok(&SimpleCacheObject<U>) - The cached entry if found and not expired
  • Err(SimpleCacheError::NotFound) - The key doesn’t exist
  • Err(SimpleCacheError::Expired) - The entry existed but expired (now removed)
§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(60));
cache.insert("user:123".to_string(), "Alice".to_string());

match cache.get(&"user:123".to_string()) {
    Ok(entry) => {
        println!("Found: {}", entry.value());
        println!("Age: {:?}", entry.age());
    }
    Err(SimpleCacheError::NotFound) => println!("User not found"),
    Err(SimpleCacheError::Expired) => println!("User data expired"),
}
Source

pub fn get_mut( &mut self, key: &T, ) -> Result<&mut SimpleCacheObject<U>, SimpleCacheError>

Retrieves a mutable reference to an entry by exact key match.

Similar to get(), but returns a mutable reference that allows you to modify the cached value in place. Expired entries are automatically removed.

§Arguments
  • key - The key to look up
§Returns
  • Ok(&mut SimpleCacheObject<U>) - Mutable reference to the cached entry
  • Err(SimpleCacheError::NotFound) - The key doesn’t exist
  • Err(SimpleCacheError::Expired) - The entry existed but expired (now removed)
§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(60));
cache.insert("counter".to_string(), 0u32);

if let Ok(entry) = cache.get_mut(&"counter".to_string()) {
    *entry.value_mut() += 1;
    assert_eq!(*entry.value(), 1);
}
Source

pub fn get_by_matcher<M>( &mut self, matcher: &M, ) -> Result<&SimpleCacheObject<U>, SimpleCacheError>
where M: Matcher<T>,

Finds the first entry matching the given matcher in O(n) time.

This method iterates through all cache entries and returns the first one that matches the provided matcher’s criteria. Expired entries encountered during the search are automatically cleaned up.

§Arguments
  • matcher - An implementation of Matcher<T> that defines the search criteria
§Returns
  • Ok(&SimpleCacheObject<U>) - The first matching entry found
  • Err(SimpleCacheError::NotFound) - No matching entries found
§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));
cache.insert("user:alice".to_string(), "Alice".to_string());
cache.insert("user:bob".to_string(), "Bob".to_string());
cache.insert("admin:charlie".to_string(), "Charlie".to_string());

let user_matcher = PrefixMatcher::new("user:");
if let Ok(user) = cache.get_by_matcher(&user_matcher) {
    println!("Found user: {}", user.value());
}
Source

pub fn get_all_by_matcher<M>( &mut self, matcher: &M, ) -> Vec<(&T, &SimpleCacheObject<U>)>
where M: Matcher<T>,

Finds all entries matching the given matcher.

This method returns all cache entries that match the provided matcher’s criteria. The cache is automatically cleaned of expired entries before searching.

§Arguments
  • matcher - An implementation of Matcher<T> that defines the search criteria
§Returns

A vector of tuples containing references to matching keys and their cached values. The vector may be empty if no matches are found.

§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));
cache.insert("user:alice".to_string(), "Alice".to_string());
cache.insert("user:bob".to_string(), "Bob".to_string());
cache.insert("admin:charlie".to_string(), "Charlie".to_string());

let user_matcher = PrefixMatcher::new("user:");
let users = cache.get_all_by_matcher(&user_matcher);
println!("Found {} users", users.len());
Source

pub fn insert(&mut self, key: T, value: U)

Inserts a new entry into the cache with the default TTL.

If the cache has a size limit and is at capacity, the oldest entry will be automatically removed to make room for the new entry (FIFO eviction). If an entry with the same key already exists, it will be replaced.

§Arguments
  • key - The key to associate with the value
  • value - The value to cache
§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));
cache.insert("user:123".to_string(), "Alice Johnson".to_string());
Source

pub fn insert_with_ttl(&mut self, key: T, value: U, ttl: Duration)

Inserts a new entry into the cache with a custom TTL.

This allows you to override the default TTL for specific entries, useful for caching data with different freshness requirements.

§Arguments
  • key - The key to associate with the value
  • value - The value to cache
  • ttl - Custom time-to-live for this specific entry
§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300)); // Default 5 min

// Cache with custom 1-hour TTL
cache.insert_with_ttl(
    "important_data".to_string(),
    "critical information".to_string(),
    Duration::from_secs(3600)
);
Source

pub fn remove(&mut self, key: &T) -> Option<SimpleCacheObject<U>>

Removes an entry by key and returns it if it existed.

This method removes the entry regardless of whether it has expired. Returns None if the key doesn’t exist.

§Arguments
  • key - The key of the entry to remove
§Returns

Some(SimpleCacheObject<U>) if the key existed, None otherwise

§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));
cache.insert("temp_data".to_string(), "temporary".to_string());

if let Some(removed) = cache.remove(&"temp_data".to_string()) {
    println!("Removed: {}", removed.into_value());
}
Source

pub fn contains_key(&self, key: &T) -> bool

Checks if a key exists in the cache and is not expired.

This is a lightweight check that doesn’t trigger cleanup of expired entries.

§Arguments
  • key - The key to check for existence
§Returns

true if the key exists and is not expired, false otherwise

§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));
cache.insert("key".to_string(), "value".to_string());

assert!(cache.contains_key(&"key".to_string()));
assert!(!cache.contains_key(&"nonexistent".to_string()));
Source

pub fn cleanup_expired(&mut self) -> usize

Manually removes all expired entries from the cache.

This method performs a full scan of the cache and removes all entries that have exceeded their TTL. This can be useful for periodic cleanup to free memory and maintain cache performance.

§Returns

The number of expired entries that were removed

§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_millis(100));
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());

// Wait for expiration
std::thread::sleep(Duration::from_millis(150));

let removed = cache.cleanup_expired();
println!("Cleaned up {} expired entries", removed);
Source

pub fn len(&self) -> usize

Returns the total number of entries in the cache (including expired ones).

Note that this includes expired entries that haven’t been cleaned up yet. Use active_len() to get only non-expired entries.

§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());

assert_eq!(cache.len(), 2);
Source

pub fn active_len(&self) -> usize

Returns the number of non-expired entries in the cache.

This method counts only entries that are still valid (not expired). It does not modify the cache or remove expired entries.

§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());

assert_eq!(cache.active_len(), 2);
Source

pub fn is_empty(&self) -> bool

Returns true if the cache contains no entries.

§Examples
use simple_cacher::*;
use std::time::Duration;

let cache = SimpleCacher::<String, String>::new(Duration::from_secs(300));
assert!(cache.is_empty());
Source

pub fn clear(&mut self)

Removes all entries from the cache.

After calling this method, the cache will be empty and len() will return 0.

§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));
cache.insert("key".to_string(), "value".to_string());
assert_eq!(cache.len(), 1);

cache.clear();
assert_eq!(cache.len(), 0);
Source

pub fn stats(&self) -> CacheStats

Returns comprehensive statistics about the cache state.

This provides detailed information about cache usage, including total entries, active (non-expired) entries, expired entries, and configuration settings.

§Returns

A CacheStats struct containing cache metrics

§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::with_max_size(Duration::from_secs(300), 1000);
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());

let stats = cache.stats();
println!("Active entries: {}", stats.active_entries);
println!("Max size: {:?}", stats.max_size);
Source

pub fn iter_active(&self) -> impl Iterator<Item = (&T, &SimpleCacheObject<U>)>

Returns an iterator over all non-expired entries in the cache.

This iterator yields tuples of (&T, &SimpleCacheObject<U>) for each active (non-expired) entry. Expired entries are skipped.

§Returns

An iterator over active cache entries

§Examples
use simple_cacher::*;
use std::time::Duration;

let mut cache = SimpleCacher::new(Duration::from_secs(300));
cache.insert("user:1".to_string(), "Alice".to_string());
cache.insert("user:2".to_string(), "Bob".to_string());

for (key, entry) in cache.iter_active() {
    println!("{}: {} (age: {:?})", key, entry.value(), entry.age());
}

Trait Implementations§

Source§

impl<T: Clone, U: Clone> Clone for SimpleCacher<T, U>

Source§

fn clone(&self) -> SimpleCacher<T, U>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug, U: Debug> Debug for SimpleCacher<T, U>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T, U> Freeze for SimpleCacher<T, U>

§

impl<T, U> RefUnwindSafe for SimpleCacher<T, U>

§

impl<T, U> Send for SimpleCacher<T, U>
where T: Send, U: Send,

§

impl<T, U> Sync for SimpleCacher<T, U>
where T: Sync, U: Sync,

§

impl<T, U> Unpin for SimpleCacher<T, U>
where T: Unpin, U: Unpin,

§

impl<T, U> UnwindSafe for SimpleCacher<T, U>
where T: UnwindSafe, U: UnwindSafe,

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.