extern crate alloc;
use core::fmt;
pub struct CacheMetadata<M = ()> {
pub size: u64,
pub last_accessed: u64,
pub create_time: u64,
pub algorithm: M,
}
impl<M: Default> CacheMetadata<M> {
#[inline]
pub fn new(size: u64) -> Self {
let now = Self::now_nanos();
Self {
size,
last_accessed: now,
create_time: now,
algorithm: M::default(),
}
}
}
impl<M> CacheMetadata<M> {
#[inline]
pub fn with_algorithm(size: u64, algorithm: M) -> Self {
let now = Self::now_nanos();
Self {
size,
last_accessed: now,
create_time: now,
algorithm,
}
}
#[inline]
pub fn touch(&mut self) {
self.last_accessed = Self::now_nanos();
}
#[inline]
pub fn age_nanos(&self) -> u64 {
Self::now_nanos().saturating_sub(self.create_time)
}
#[inline]
pub fn idle_nanos(&self) -> u64 {
Self::now_nanos().saturating_sub(self.last_accessed)
}
#[cfg(feature = "std")]
#[inline]
fn now_nanos() -> u64 {
extern crate std;
use std::time::{SystemTime, UNIX_EPOCH};
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos() as u64)
.unwrap_or(0)
}
#[cfg(not(feature = "std"))]
#[inline]
fn now_nanos() -> u64 {
0
}
}
impl<M: Clone> Clone for CacheMetadata<M> {
fn clone(&self) -> Self {
Self {
size: self.size,
last_accessed: self.last_accessed,
create_time: self.create_time,
algorithm: self.algorithm.clone(),
}
}
}
impl<M: fmt::Debug> fmt::Debug for CacheMetadata<M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CacheMetadata")
.field("size", &self.size)
.field("last_accessed", &self.last_accessed)
.field("create_time", &self.create_time)
.field("algorithm", &self.algorithm)
.finish()
}
}
pub struct CacheEntry<K, V, M = ()> {
pub key: K,
pub value: V,
pub metadata: CacheMetadata<M>,
}
impl<K, V, M: Default> CacheEntry<K, V, M> {
#[inline]
pub fn new(key: K, value: V, size: u64) -> Self {
Self {
key,
value,
metadata: CacheMetadata::new(size),
}
}
}
impl<K, V, M> CacheEntry<K, V, M> {
#[inline]
pub fn with_algorithm_metadata(key: K, value: V, size: u64, algorithm_meta: M) -> Self {
Self {
key,
value,
metadata: CacheMetadata::with_algorithm(size, algorithm_meta),
}
}
#[inline]
pub fn touch(&mut self) {
self.metadata.touch();
}
#[inline]
pub fn age_nanos(&self) -> u64 {
self.metadata.age_nanos()
}
#[inline]
pub fn idle_nanos(&self) -> u64 {
self.metadata.idle_nanos()
}
#[inline]
pub fn size(&self) -> u64 {
self.metadata.size
}
}
impl<K: Clone, V: Clone, M: Clone> Clone for CacheEntry<K, V, M> {
fn clone(&self) -> Self {
Self {
key: self.key.clone(),
value: self.value.clone(),
metadata: self.metadata.clone(),
}
}
}
impl<K: fmt::Debug, V: fmt::Debug, M: fmt::Debug> fmt::Debug for CacheEntry<K, V, M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CacheEntry")
.field("key", &self.key)
.field("value", &self.value)
.field("metadata", &self.metadata)
.finish()
}
}
#[cfg(test)]
mod tests {
extern crate alloc;
use super::*;
use alloc::format;
use alloc::vec;
#[test]
fn test_new_entry() {
let entry: CacheEntry<&str, i32> = CacheEntry::new("key", 42, 1);
assert_eq!(entry.key, "key");
assert_eq!(entry.value, 42);
assert_eq!(entry.metadata.size, 1);
}
#[test]
fn test_entry_with_algorithm_metadata() {
#[derive(Debug, Clone, PartialEq, Default)]
struct TestMeta {
frequency: u64,
}
let entry =
CacheEntry::with_algorithm_metadata("key", "value", 5, TestMeta { frequency: 10 });
assert_eq!(entry.key, "key");
assert_eq!(entry.value, "value");
assert_eq!(entry.metadata.size, 5);
assert_eq!(entry.metadata.algorithm.frequency, 10);
}
#[test]
fn test_touch_updates_last_accessed() {
let mut entry: CacheEntry<&str, i32> = CacheEntry::new("key", 42, 1);
let initial = entry.metadata.last_accessed;
entry.touch();
let updated = entry.metadata.last_accessed;
assert!(updated >= initial);
}
#[test]
fn test_clone_entry() {
#[derive(Debug, Clone, PartialEq, Default)]
struct TestMeta {
value: u64,
}
let entry =
CacheEntry::with_algorithm_metadata("key", vec![1, 2, 3], 3, TestMeta { value: 100 });
let cloned = entry.clone();
assert_eq!(cloned.key, entry.key);
assert_eq!(cloned.value, entry.value);
assert_eq!(cloned.metadata.size, entry.metadata.size);
assert_eq!(cloned.metadata.algorithm, entry.metadata.algorithm);
}
#[test]
fn test_age_and_idle() {
let mut entry: CacheEntry<&str, i32> = CacheEntry::new("key", 42, 1);
let _age = entry.age_nanos();
let _idle = entry.idle_nanos();
entry.touch();
let _idle_after = entry.idle_nanos();
}
#[test]
fn test_metadata_size() {
let meta: CacheMetadata<()> = CacheMetadata::new(1024);
assert_eq!(meta.size, 1024);
}
#[test]
fn test_debug_impl() {
let entry: CacheEntry<&str, i32> = CacheEntry::new("key", 42, 1);
let debug_str = format!("{:?}", entry);
assert!(debug_str.contains("CacheEntry"));
assert!(debug_str.contains("key"));
assert!(debug_str.contains("42"));
}
}