aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLizzy Fleckenstein <lizzy@vlhl.dev>2026-05-10 16:45:35 +0200
committerLizzy Fleckenstein <lizzy@vlhl.dev>2026-05-10 16:45:35 +0200
commitc689b47d44e8fdf03b25284014df139e990557f3 (patch)
tree3f0ceede184e457cf136c428a83da65aec22d35e
parent448d4c630b4b06ee2870205c1d9267413caf24df (diff)
downloadazalea-drasl-c689b47d44e8fdf03b25284014df139e990557f3.tar.xz
support generic auth cache entries
-rw-r--r--azalea-auth/src/cache.rs51
1 files changed, 41 insertions, 10 deletions
diff --git a/azalea-auth/src/cache.rs b/azalea-auth/src/cache.rs
index 62921773..3ff93330 100644
--- a/azalea-auth/src/cache.rs
+++ b/azalea-auth/src/cache.rs
@@ -1,12 +1,13 @@
//! Cache auth information
use std::{
+ fmt::Debug,
io,
path::Path,
time::{SystemTime, UNIX_EPOCH},
};
-use serde::{Deserialize, Serialize};
+use serde::{Deserialize, Serialize, de::DeserializeOwned};
use thiserror::Error;
use tokio::{
fs::{self, File},
@@ -26,6 +27,13 @@ pub enum CacheError {
Parse(serde_json::Error),
}
+pub trait CacheEntry: Serialize + DeserializeOwned + Debug {
+ type Key<'a>: for<'b> PartialEq<Self::Key<'b>>
+ where
+ Self: 'a;
+ fn key<'a>(&'a self) -> Self::Key<'a>;
+}
+
#[derive(Debug, Deserialize, Serialize)]
pub struct CachedAccount {
#[serde(alias = "email")]
@@ -40,6 +48,13 @@ pub struct CachedAccount {
pub profile: crate::auth::ProfileResponse,
}
+impl CacheEntry for CachedAccount {
+ type Key<'a> = &'a str;
+ fn key<'a>(&'a self) -> Self::Key<'a> {
+ &self.cache_key
+ }
+}
+
#[derive(Debug, Deserialize, Serialize)]
pub struct ExpiringValue<T> {
/// Seconds since the UNIX epoch
@@ -75,8 +90,8 @@ impl<T: Clone> Clone for ExpiringValue<T> {
}
}
-async fn get_entire_cache(cache_file: &Path) -> Result<Vec<CachedAccount>, CacheError> {
- let mut cache: Vec<CachedAccount> = Vec::new();
+async fn get_entire_cache<T: CacheEntry>(cache_file: &Path) -> Result<Vec<T>, CacheError> {
+ let mut cache: Vec<T> = Vec::new();
if cache_file.exists() {
let mut cache_file = File::open(cache_file).await.map_err(CacheError::Read)?;
// read the file into a string
@@ -89,7 +104,10 @@ async fn get_entire_cache(cache_file: &Path) -> Result<Vec<CachedAccount>, Cache
}
Ok(cache)
}
-async fn set_entire_cache(cache_file: &Path, cache: Vec<CachedAccount>) -> Result<(), CacheError> {
+async fn set_entire_cache<T: CacheEntry>(
+ cache_file: &Path,
+ cache: Vec<T>,
+) -> Result<(), CacheError> {
trace!("saving cache: {:?}", cache);
if !cache_file.exists() {
@@ -118,10 +136,15 @@ async fn set_entire_cache(cache_file: &Path, cache: Vec<CachedAccount>) -> Resul
///
/// As a convention, the cache key is usually the email of the account.
pub async fn get_account_in_cache(cache_file: &Path, cache_key: &str) -> Option<CachedAccount> {
- let cache = get_entire_cache(cache_file).await.unwrap_or_default();
- cache
- .into_iter()
- .find(|account| account.cache_key == cache_key)
+ get_account_in_cache_g(cache_file, cache_key).await
+}
+
+pub async fn get_account_in_cache_g<T: CacheEntry>(
+ cache_file: &Path,
+ cache_key: T::Key<'_>,
+) -> Option<T> {
+ let cache = get_entire_cache::<T>(cache_file).await.unwrap_or_default();
+ cache.into_iter().find(|account| account.key() == cache_key)
}
pub async fn set_account_in_cache(
@@ -129,8 +152,16 @@ pub async fn set_account_in_cache(
cache_key: &str,
account: CachedAccount,
) -> Result<(), CacheError> {
- let mut cache = get_entire_cache(cache_file).await.unwrap_or_default();
- cache.retain(|account| account.cache_key != cache_key);
+ set_account_in_cache_g(cache_file, cache_key, account).await
+}
+
+pub async fn set_account_in_cache_g<T: CacheEntry>(
+ cache_file: &Path,
+ cache_key: T::Key<'_>,
+ account: T,
+) -> Result<(), CacheError> {
+ let mut cache = get_entire_cache::<T>(cache_file).await.unwrap_or_default();
+ cache.retain(|account| account.key() != cache_key);
cache.push(account);
set_entire_cache(cache_file, cache).await
}