Files
pmomusic/pmocache/examples/README_EXAMPLES.md

5.4 KiB

Exemples du module Download

Ce répertoire contient des exemples d'utilisation du module download de pmocache.

Fichiers

test_download.rs

Exemple basique de téléchargement sans transformation.

Utilisation:

cargo run --example test_download

test_download_transformer.rs

Exemples complets de transformers :

  • Transformation en majuscules
  • Suppression de header (skip N bytes)
  • Numérotation des lignes
  • Compression GZIP (commenté, nécessite async-compression)

Utilisation:

cargo run --example test_download_transformer

simple_transformer.rs

Exemple de documentation montrant la syntaxe et l'API.

Utilisation:

cargo run --example simple_transformer

Concepts clés

1. Téléchargement simple

use pmocache::download::download;

let dl = download("/tmp/file.dat", "https://example.com/file.dat");
dl.wait_until_finished().await?;

2. Téléchargement avec transformer

Un transformer est une fonction qui :

  1. Reçoit le stream de réponse HTTP
  2. Reçoit un fichier ouvert en écriture
  3. Reçoit un callback de progression
  4. Traite les données à la volée
  5. Écrit le résultat transformé dans le fichier
let transformer: StreamTransformer = Box::new(|response, mut file, update_progress| {
    Box::pin(async move {
        let mut stream = response.bytes_stream();
        let mut total = 0u64;

        while let Some(chunk_result) = stream.next().await {
            let chunk = chunk_result.map_err(|e| e.to_string())?;

            // Transformer les données
            let transformed = your_transformation(&chunk);

            // Écrire le résultat
            file.write_all(&transformed).await.map_err(|e| e.to_string())?;

            // Mettre à jour la progression
            total += transformed.len() as u64;
            update_progress(total);
        }

        file.flush().await.map_err(|e| e.to_string())?;
        Ok(())
    })
});

let dl = download_with_transformer("/tmp/output.dat", "https://example.com/input.dat", Some(transformer));

3. Suivi de progression

let dl = download("/tmp/file.dat", "https://example.com/file.dat");

// Attendre au moins 1MB
dl.wait_until_min_size(1024 * 1024).await?;
println!("Au moins 1MB téléchargés");

// Voir la progression
loop {
    let current = dl.current_size().await;
    let expected = dl.expected_size().await;

    if let Some(total) = expected {
        println!("Progression: {}/{} bytes ({:.1}%)",
            current, total, 100.0 * current as f64 / total as f64);
    } else {
        println!("Téléchargés: {} bytes", current);
    }

    if dl.finished().await {
        break;
    }

    tokio::time::sleep(Duration::from_millis(100)).await;
}

Cas d'usage pour PMOMusic

Conversion d'images pour le cache

// Télécharger une couverture d'album et la convertir en WebP
fn webp_transformer() -> StreamTransformer {
    Box::new(|response, mut file, update_progress| {
        Box::pin(async move {
            let bytes = response.bytes().await.map_err(|e| e.to_string())?;
            let img = image::load_from_memory(&bytes)
                .map_err(|e| format!("Decode error: {}", e))?;

            let encoder = webp::Encoder::from_image(&img)
                .map_err(|e| format!("Encode error: {}", e))?;
            let webp = encoder.encode(75.0);

            file.write_all(&*webp).await.map_err(|e| e.to_string())?;
            file.flush().await.map_err(|e| e.to_string())?;

            update_progress(webp.len() as u64);
            Ok(())
        })
    })
}

// Utilisation dans pmocovers
let transformer = webp_transformer();
let dl = download_with_transformer(cache_path, cover_url, Some(transformer));

Conversion audio pour le cache

// Télécharger du MP3 et le convertir en FLAC
fn mp3_to_flac_transformer() -> StreamTransformer {
    Box::new(|response, mut file, update_progress| {
        Box::pin(async move {
            let mp3_bytes = response.bytes().await.map_err(|e| e.to_string())?;

            // Décoder MP3
            let decoded = decode_mp3(&mp3_bytes)?;

            // Encoder FLAC
            let flac_bytes = encode_flac(&decoded)?;

            file.write_all(&flac_bytes).await.map_err(|e| e.to_string())?;
            file.flush().await.map_err(|e| e.to_string())?;

            update_progress(flac_bytes.len() as u64);
            Ok(())
        })
    })
}

// Utilisation dans pmoaudiocache
let transformer = mp3_to_flac_transformer();
let dl = download_with_transformer(cache_path, audio_url, Some(transformer));

Streaming progressif

// Commencer à lire pendant le téléchargement
let dl = download(audio_path, stream_url);

// Attendre le buffer minimal (256KB)
dl.wait_until_min_size(256 * 1024).await?;

// Ouvrir et commencer à lire
let mut file = dl.open()?;
let mut buffer = [0u8; 4096];

loop {
    // Lire ce qui est disponible
    match file.read(&mut buffer) {
        Ok(0) if dl.finished().await => break, // EOF
        Ok(0) => {
            // Pas encore de données, attendre un peu
            tokio::time::sleep(Duration::from_millis(10)).await;
        }
        Ok(n) => {
            // Traiter les données lues
            process_audio_chunk(&buffer[..n]);
        }
        Err(e) => return Err(e.into()),
    }
}

Voir aussi