Files
pmomusic/pmocache/src/config_ext.rs

226 lines
7.8 KiB
Rust

//! Extension pour intégrer la gestion des caches dans pmoconfig
//!
//! Ce module fournit le trait `CacheConfigExt` qui permet d'ajouter facilement
//! des méthodes de gestion de cache générique à pmoconfig::Config.
//!
//! Il propose également un macro `impl_cache_config_ext!` pour simplifier
//! l'implémentation de traits d'extension spécialisés (audio, covers, etc.).
use anyhow::Result;
use pmoconfig::Config;
use serde_yaml::{Number, Value};
use std::sync::Arc;
/// Trait d'extension pour ajouter la gestion des caches à pmoconfig
///
/// Ce trait étend `pmoconfig::Config` avec des méthodes génériques pour gérer
/// n'importe quel type de cache (audio, images, etc.).
///
/// # Exemple
///
/// ```rust,ignore
/// use pmoconfig::get_config;
/// use pmocache::{CacheConfigExt, AudioConfig};
///
/// let config = get_config();
/// let cache_dir = config.get_cache_dir("audio_cache", "cache_audio")?;
/// let cache_size = config.get_cache_size("audio_cache", 500)?;
/// ```
pub trait CacheConfigExt {
/// Récupère le répertoire d'un cache
///
/// # Arguments
///
/// * `cache_type` - Type de cache (ex: "audio_cache", "cover_cache")
/// * `default` - Nom de répertoire par défaut si non configuré
///
/// # Returns
///
/// Le chemin absolu du répertoire du cache
fn get_cache_dir(&self, cache_type: &str, default: &str) -> Result<String>;
/// Définit le répertoire d'un cache
///
/// # Arguments
///
/// * `cache_type` - Type de cache (ex: "audio_cache", "cover_cache")
/// * `directory` - Chemin du répertoire (absolu ou relatif au config_dir)
fn set_cache_dir(&self, cache_type: &str, directory: String) -> Result<()>;
/// Récupère la taille maximale d'un cache
///
/// # Arguments
///
/// * `cache_type` - Type de cache (ex: "audio_cache", "cover_cache")
/// * `default` - Taille par défaut si non configurée
///
/// # Returns
///
/// Le nombre maximal d'éléments dans le cache
fn get_cache_size(&self, cache_type: &str, default: usize) -> Result<usize>;
/// Définit la taille maximale d'un cache
///
/// # Arguments
///
/// * `cache_type` - Type de cache (ex: "audio_cache", "cover_cache")
/// * `size` - Nombre maximal d'éléments
fn set_cache_size(&self, cache_type: &str, size: usize) -> Result<()>;
/// Crée une instance de cache générique configurée
///
/// Cette méthode factory crée un cache en utilisant les paramètres
/// de configuration (répertoire et taille).
///
/// # Arguments
///
/// * `cache_type` - Type de cache (ex: "audio_cache", "cover_cache")
/// * `default_dir` - Répertoire par défaut
/// * `default_size` - Taille par défaut
///
/// # Returns
///
/// Une instance Arc du cache configuré
///
/// # Exemple
///
/// ```rust,ignore
/// use pmoconfig::get_config;
/// use pmocache::{CacheConfigExt, AudioConfig};
///
/// let config = get_config();
/// let cache = config.create_cache::<AudioConfig>("audio_cache", "cache_audio", 500)?;
/// ```
fn create_cache<C: crate::CacheConfig + 'static>(
&self,
cache_type: &str,
default_dir: &str,
default_size: usize,
) -> Result<Arc<crate::Cache<C>>>;
}
impl CacheConfigExt for Config {
fn get_cache_dir(&self, cache_type: &str, default: &str) -> Result<String> {
self.get_managed_dir(&["host", cache_type, "directory"], default)
}
fn set_cache_dir(&self, cache_type: &str, directory: String) -> Result<()> {
self.set_managed_dir(&["host", cache_type, "directory"], directory)
}
fn get_cache_size(&self, cache_type: &str, default: usize) -> Result<usize> {
match self.get_value(&["host", cache_type, "size"])? {
Value::Number(n) if n.is_i64() => Ok(n.as_i64().unwrap() as usize),
Value::Number(n) if n.is_u64() => Ok(n.as_u64().unwrap() as usize),
_ => Ok(default),
}
}
fn set_cache_size(&self, cache_type: &str, size: usize) -> Result<()> {
let n = Number::from(size);
self.set_value(&["host", cache_type, "size"], Value::Number(n))
}
fn create_cache<C: crate::CacheConfig + 'static>(
&self,
cache_type: &str,
default_dir: &str,
default_size: usize,
) -> Result<Arc<crate::Cache<C>>> {
let dir = self.get_cache_dir(cache_type, default_dir)?;
let size = self.get_cache_size(cache_type, default_size)?;
Ok(Arc::new(crate::Cache::<C>::new(&dir, size)?))
}
}
/// Macro pour simplifier l'implémentation de traits d'extension de cache spécialisés
///
/// Ce macro génère automatiquement un trait d'extension pour `pmoconfig::Config`
/// avec des méthodes spécifiques à un type de cache (audio, covers, etc.).
///
/// # Arguments
///
/// * `trait_name` - Nom du trait à générer (ex: `AudioCacheConfigExt`)
/// * `cache_type` - Type de cache dans la config (ex: `"audio_cache"`)
/// * `default_dir` - Répertoire par défaut (ex: `"cache_audio"`)
/// * `default_size` - Taille par défaut (ex: `500`)
/// * `cache_struct` - Type du cache (ex: `crate::Cache`)
/// * `constructor` - Expression pour construire le cache (ex: `crate::cache::new_cache(&dir, size)`)
///
/// # Exemple
///
/// ```rust,ignore
/// use pmocache::impl_cache_config_ext;
///
/// impl_cache_config_ext! {
/// AudioCacheConfigExt,
/// "audio_cache",
/// "cache_audio",
/// 500,
/// crate::Cache,
/// |dir, size| crate::cache::new_cache(dir, size)
/// }
/// ```
///
/// Cela génère un trait avec les méthodes :
/// - `get_audiocache_dir()` / `set_audiocache_dir()`
/// - `get_audiocache_size()` / `set_audiocache_size()`
/// - `create_audio_cache()`
#[macro_export]
macro_rules! impl_cache_config_ext {
(
$trait_name:ident,
$cache_type:expr,
$default_dir:expr,
$default_size:expr,
$cache_type_struct:ty,
$constructor:expr
) => {
pub trait $trait_name {
/// Récupère le répertoire du cache
fn get_cache_dir_ext(&self) -> anyhow::Result<String>;
/// Définit le répertoire du cache
fn set_cache_dir_ext(&self, directory: String) -> anyhow::Result<()>;
/// Récupère la taille maximale du cache
fn get_cache_size_ext(&self) -> anyhow::Result<usize>;
/// Définit la taille maximale du cache
fn set_cache_size_ext(&self, size: usize) -> anyhow::Result<()>;
/// Crée une instance du cache configurée
fn create_cache_ext(&self) -> anyhow::Result<std::sync::Arc<$cache_type_struct>>;
}
impl $trait_name for pmoconfig::Config {
fn get_cache_dir_ext(&self) -> anyhow::Result<String> {
use $crate::CacheConfigExt;
self.get_cache_dir($cache_type, $default_dir)
}
fn set_cache_dir_ext(&self, directory: String) -> anyhow::Result<()> {
use $crate::CacheConfigExt;
self.set_cache_dir($cache_type, directory)
}
fn get_cache_size_ext(&self) -> anyhow::Result<usize> {
use $crate::CacheConfigExt;
self.get_cache_size($cache_type, $default_size)
}
fn set_cache_size_ext(&self, size: usize) -> anyhow::Result<()> {
use $crate::CacheConfigExt;
self.set_cache_size($cache_type, size)
}
fn create_cache_ext(&self) -> anyhow::Result<std::sync::Arc<$cache_type_struct>> {
let dir = self.get_cache_dir_ext()?;
let size = self.get_cache_size_ext()?;
let constructor = $constructor;
Ok(std::sync::Arc::new(constructor(&dir, size)?))
}
}
};
}