use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct CacheEntry<T> {
pub value: T,
created_at: Instant,
last_accessed: Instant,
access_count: u64,
}
impl<T> CacheEntry<T> {
pub fn new(value: T) -> Self {
let now = Instant::now();
Self {
value,
created_at: now,
last_accessed: now,
access_count: 0,
}
}
pub fn age(&self) -> Duration {
self.created_at.elapsed()
}
pub fn is_expired(&self, ttl: Duration) -> bool {
self.age() > ttl
}
pub fn time_since_access(&self) -> Duration {
self.last_accessed.elapsed()
}
pub fn access_count(&self) -> u64 {
self.access_count
}
pub fn touch(&mut self) {
self.last_accessed = Instant::now();
self.access_count += 1;
}
pub fn get(&mut self) -> &T {
self.touch();
&self.value
}
pub fn get_mut(&mut self) -> &mut T {
self.touch();
&mut self.value
}
pub fn clone_value(&mut self) -> T
where
T: Clone,
{
self.touch();
self.value.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::thread;
#[test]
fn test_cache_entry_creation() {
let entry = CacheEntry::new(42);
assert_eq!(entry.value, 42);
assert_eq!(entry.access_count(), 0);
}
#[test]
fn test_cache_entry_age() {
let entry = CacheEntry::new("test");
thread::sleep(Duration::from_millis(10));
assert!(entry.age() >= Duration::from_millis(10));
}
#[test]
fn test_cache_entry_expiration() {
let entry = CacheEntry::new("test");
assert!(!entry.is_expired(Duration::from_secs(60)));
assert!(entry.is_expired(Duration::from_secs(0)));
}
#[test]
fn test_cache_entry_access_tracking() {
let mut entry = CacheEntry::new(100);
assert_eq!(entry.access_count(), 0);
entry.touch();
assert_eq!(entry.access_count(), 1);
entry.touch();
assert_eq!(entry.access_count(), 2);
}
#[test]
fn test_cache_entry_get() {
let mut entry = CacheEntry::new(42);
assert_eq!(entry.access_count(), 0);
let value = entry.get();
assert_eq!(*value, 42);
assert_eq!(entry.access_count(), 1);
let value = entry.get();
assert_eq!(*value, 42);
assert_eq!(entry.access_count(), 2);
}
#[test]
fn test_cache_entry_get_mut() {
let mut entry = CacheEntry::new(42);
{
let value = entry.get_mut();
*value = 100;
}
assert_eq!(entry.value, 100);
assert_eq!(entry.access_count(), 1);
}
#[test]
fn test_cache_entry_clone_value() {
let mut entry = CacheEntry::new(vec![1, 2, 3]);
let cloned = entry.clone_value();
assert_eq!(cloned, vec![1, 2, 3]);
assert_eq!(entry.access_count(), 1);
}
#[test]
fn test_time_since_access() {
let mut entry = CacheEntry::new("test");
entry.touch();
thread::sleep(Duration::from_millis(10));
assert!(entry.time_since_access() >= Duration::from_millis(10));
}
}