diff options
| author | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-05-10 16:45:35 +0200 |
|---|---|---|
| committer | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-05-10 16:45:35 +0200 |
| commit | c689b47d44e8fdf03b25284014df139e990557f3 (patch) | |
| tree | 3f0ceede184e457cf136c428a83da65aec22d35e | |
| parent | 448d4c630b4b06ee2870205c1d9267413caf24df (diff) | |
| download | azalea-drasl-c689b47d44e8fdf03b25284014df139e990557f3.tar.xz | |
support generic auth cache entries
| -rw-r--r-- | azalea-auth/src/cache.rs | 51 |
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 } |
