#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
use drivers::{Driver, Error};
use serde::{de::DeserializeOwned, Serialize};
use std::{sync::Arc, time::Duration};
pub mod drivers;
#[derive(Debug, Clone)]
pub struct Cache {
driver: Arc<dyn Driver>,
}
impl Cache {
pub fn new<D: Driver + 'static>(driver: D) -> Self {
Self {
driver: Arc::new(driver),
}
}
pub async fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, Error> {
let Some(bytes) = self.driver.get(key).await? else {
return Ok(None);
};
bitcode::deserialize(&bytes)
.map(Some)
.map_err(|e| Error::Serialization(Box::new(e)))
}
pub async fn has(&self, key: &str) -> Result<bool, Error> {
self.driver.has(key).await
}
pub async fn remember<T: Serialize + DeserializeOwned + Send + Sync>(
&self,
key: &str,
duration: Duration,
value: T,
) -> Result<T, Error> {
if let Some(existing) = self.get::<T>(key).await? {
return Ok(existing);
}
self.put(key, &value, duration).await?;
Ok(value)
}
pub async fn remember_forever<T: Serialize + DeserializeOwned + Send + Sync>(
&self,
key: &str,
value: T,
) -> Result<T, Error> {
if let Some(existing) = self.get::<T>(key).await? {
return Ok(existing);
}
self.forever(key, &value).await?;
Ok(value)
}
pub async fn pull<T: DeserializeOwned + Send>(&self, key: &str) -> Result<Option<T>, Error> {
let Some(item) = self.get(key).await? else {
return Ok(None);
};
self.forget(key).await?;
Ok(Some(item))
}
pub async fn put<T: Serialize + Sync>(
&self,
key: &str,
value: &T,
expiry: Duration,
) -> Result<(), Error> {
let bytes = bitcode::serialize(value).map_err(|e| Error::Serialization(Box::new(e)))?;
self.driver.put(key, bytes, Some(expiry)).await
}
pub async fn add<T: Serialize + Send + Sync>(
&self,
key: &str,
value: T,
expiry: Duration,
) -> Result<bool, Error> {
if self.has(key).await? {
return Ok(false);
}
self.put(key, &value, expiry).await?;
Ok(true)
}
pub async fn forever<T: Serialize + Send + Sync>(
&self,
key: &str,
value: &T,
) -> Result<(), Error> {
let bytes = bitcode::serialize(value).map_err(|e| Error::Serialization(Box::new(e)))?;
self.driver.put(key, bytes, None).await
}
pub async fn forget(&self, key: &str) -> Result<(), Error> {
self.driver.forget(key).await
}
pub async fn flush(&self) -> Result<(), Error> {
self.driver.flush().await
}
}