use anyhow::Result;
use std::collections::HashMap;
use std::time::Duration;
use super::types::{CacheKey, CacheSizeInfo, CacheValue, StorageStatistics};
pub trait CacheStorage: Send + Sync + std::fmt::Debug {
fn store(&mut self, key: CacheKey, value: CacheValue, ttl: Option<Duration>) -> Result<()>;
fn retrieve(&self, key: &CacheKey) -> Option<CacheValue>;
fn remove(&mut self, key: &CacheKey) -> bool;
fn size_info(&self) -> CacheSizeInfo;
fn clear(&mut self);
fn statistics(&self) -> StorageStatistics;
}
#[derive(Debug)]
pub struct MemoryStorage {
data: HashMap<CacheKey, CacheValue>,
max_size: u64,
current_size: u64,
}
impl MemoryStorage {
pub fn new(max_size: u64) -> Self {
Self {
data: HashMap::new(),
max_size,
current_size: 0,
}
}
}
impl CacheStorage for MemoryStorage {
fn store(&mut self, key: CacheKey, value: CacheValue, _ttl: Option<Duration>) -> Result<()> {
let size = value.metadata.size_bytes;
if self.current_size + size <= self.max_size {
self.data.insert(key, value);
self.current_size += size;
}
Ok(())
}
fn retrieve(&self, key: &CacheKey) -> Option<CacheValue> {
self.data.get(key).cloned()
}
fn remove(&mut self, key: &CacheKey) -> bool {
if let Some(value) = self.data.remove(key) {
self.current_size -= value.metadata.size_bytes;
true
} else {
false
}
}
fn size_info(&self) -> CacheSizeInfo {
CacheSizeInfo {
used_bytes: self.current_size,
available_bytes: self.max_size - self.current_size,
total_capacity_bytes: self.max_size,
item_count: self.data.len() as u64,
}
}
fn clear(&mut self) {
self.data.clear();
self.current_size = 0;
}
fn statistics(&self) -> StorageStatistics {
StorageStatistics::default()
}
}
#[derive(Debug)]
pub struct CompressedStorage {
inner: MemoryStorage,
}
impl CompressedStorage {
pub fn new(max_size: u64) -> Self {
Self {
inner: MemoryStorage::new(max_size),
}
}
}
impl CacheStorage for CompressedStorage {
fn store(&mut self, key: CacheKey, value: CacheValue, ttl: Option<Duration>) -> Result<()> {
self.inner.store(key, value, ttl)
}
fn retrieve(&self, key: &CacheKey) -> Option<CacheValue> {
self.inner.retrieve(key)
}
fn remove(&mut self, key: &CacheKey) -> bool {
self.inner.remove(key)
}
fn size_info(&self) -> CacheSizeInfo {
self.inner.size_info()
}
fn clear(&mut self) {
self.inner.clear()
}
fn statistics(&self) -> StorageStatistics {
self.inner.statistics()
}
}
#[derive(Debug)]
pub struct PersistentStorage {
inner: MemoryStorage,
}
impl PersistentStorage {
pub fn new(max_size: u64) -> Result<Self> {
Ok(Self {
inner: MemoryStorage::new(max_size),
})
}
}
impl CacheStorage for PersistentStorage {
fn store(&mut self, key: CacheKey, value: CacheValue, ttl: Option<Duration>) -> Result<()> {
self.inner.store(key, value, ttl)
}
fn retrieve(&self, key: &CacheKey) -> Option<CacheValue> {
self.inner.retrieve(key)
}
fn remove(&mut self, key: &CacheKey) -> bool {
self.inner.remove(key)
}
fn size_info(&self) -> CacheSizeInfo {
self.inner.size_info()
}
fn clear(&mut self) {
self.inner.clear()
}
fn statistics(&self) -> StorageStatistics {
self.inner.statistics()
}
}