annil/
provider.rs

1use anni_provider::{AnniProvider, ProviderError};
2use std::ops::{Deref, DerefMut};
3use tokio::sync::RwLock;
4
5pub struct AnnilProvider<T: AnniProvider + Send + Sync>(RwLock<T>);
6
7impl<T: AnniProvider + Send + Sync> AnnilProvider<T> {
8    pub fn new(provider: T) -> Self {
9        Self(RwLock::new(provider))
10    }
11
12    pub async fn compute_etag(&self) -> Result<String, ProviderError> {
13        use base64::engine::general_purpose::STANDARD;
14        use base64::Engine;
15
16        let provider = self.0.read().await;
17
18        let mut etag = 0;
19        for album in provider.albums().await? {
20            if let Ok(uuid) = uuid::Uuid::parse_str(album.as_ref()) {
21                etag ^= uuid.as_u128();
22            } else {
23                log::error!("Failed to parse uuid: {album}");
24            }
25        }
26
27        Ok(format!(r#""{}""#, STANDARD.encode(etag.to_be_bytes())))
28    }
29}
30
31impl<T: AnniProvider + Send + Sync> Deref for AnnilProvider<T> {
32    type Target = RwLock<T>;
33
34    fn deref(&self) -> &Self::Target {
35        &self.0
36    }
37}
38
39impl<T: AnniProvider + Send + Sync> DerefMut for AnnilProvider<T> {
40    fn deref_mut(&mut self) -> &mut Self::Target {
41        &mut self.0
42    }
43}