305 lines
10 KiB
Rust
305 lines
10 KiB
Rust
// Exemple d'utilisation du module download avec transformations
|
|
|
|
use futures_util::StreamExt;
|
|
use pmocache::download::{download_with_transformer, StreamTransformer};
|
|
use tokio::io::AsyncWriteExt;
|
|
|
|
/// Exemple de transformer qui compresse les données en gzip
|
|
///
|
|
/// Note: Cette fonction nécessite la dépendance `async-compression`
|
|
/// Pour l'utiliser, ajoutez à Cargo.toml:
|
|
/// ```toml
|
|
/// [dev-dependencies]
|
|
/// async-compression = { version = "0.4", features = ["tokio", "gzip"] }
|
|
/// ```
|
|
#[allow(dead_code)]
|
|
fn create_gzip_transformer() -> StreamTransformer {
|
|
// Commenté car nécessite async-compression
|
|
// Décommentez si vous ajoutez la dépendance
|
|
unimplemented!("Cette fonction nécessite la dépendance async-compression")
|
|
|
|
/*
|
|
Box::new(|response, mut file, context| {
|
|
Box::pin(async move {
|
|
use async_compression::tokio::write::GzipEncoder;
|
|
|
|
let mut encoder = GzipEncoder::new(&mut file);
|
|
let mut stream = response.bytes_stream();
|
|
let mut total_written = 0u64;
|
|
|
|
while let Some(chunk_result) = stream.next().await {
|
|
let chunk = chunk_result.map_err(|e| format!("Failed to read chunk: {}", e))?;
|
|
|
|
encoder
|
|
.write_all(&chunk)
|
|
.await
|
|
.map_err(|e| format!("Failed to write compressed data: {}", e))?;
|
|
|
|
total_written += chunk.len() as u64;
|
|
context.report_progress(total_written);
|
|
}
|
|
|
|
encoder
|
|
.shutdown()
|
|
.await
|
|
.map_err(|e| format!("Failed to finalize compression: {}", e))?;
|
|
|
|
Ok(())
|
|
})
|
|
})
|
|
*/
|
|
}
|
|
|
|
/// Exemple de transformer qui convertit les données en majuscules (exemple simple)
|
|
fn create_uppercase_transformer() -> StreamTransformer {
|
|
Box::new(|input, mut file, context| {
|
|
Box::pin(async move {
|
|
let mut stream = input.into_byte_stream();
|
|
let mut total_written = 0u64;
|
|
|
|
while let Some(chunk_result) = stream.next().await {
|
|
let chunk = chunk_result?;
|
|
|
|
// Transformer en majuscules (seulement pour texte ASCII)
|
|
let transformed: Vec<u8> = chunk
|
|
.iter()
|
|
.map(|&b| {
|
|
if b.is_ascii_lowercase() {
|
|
b.to_ascii_uppercase()
|
|
} else {
|
|
b
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
file.write_all(&transformed)
|
|
.await
|
|
.map_err(|e| format!("Failed to write: {}", e))?;
|
|
|
|
total_written += transformed.len() as u64;
|
|
context.report_progress(total_written);
|
|
}
|
|
|
|
file.flush()
|
|
.await
|
|
.map_err(|e| format!("Failed to flush: {}", e))?;
|
|
|
|
Ok(())
|
|
})
|
|
})
|
|
}
|
|
|
|
/// Exemple de transformer qui saute les N premiers bytes (utile pour enlever des headers)
|
|
fn create_skip_header_transformer(skip_bytes: usize) -> StreamTransformer {
|
|
Box::new(move |input, mut file, context| {
|
|
Box::pin(async move {
|
|
let mut stream = input.into_byte_stream();
|
|
let mut skipped = 0usize;
|
|
let mut total_written = 0u64;
|
|
|
|
while let Some(chunk_result) = stream.next().await {
|
|
let chunk = chunk_result?;
|
|
|
|
let to_write = if skipped < skip_bytes {
|
|
let remaining_to_skip = skip_bytes - skipped;
|
|
if chunk.len() <= remaining_to_skip {
|
|
skipped += chunk.len();
|
|
continue;
|
|
} else {
|
|
skipped = skip_bytes;
|
|
&chunk[remaining_to_skip..]
|
|
}
|
|
} else {
|
|
&chunk[..]
|
|
};
|
|
|
|
file.write_all(to_write)
|
|
.await
|
|
.map_err(|e| format!("Failed to write: {}", e))?;
|
|
|
|
total_written += to_write.len() as u64;
|
|
context.report_progress(total_written);
|
|
}
|
|
|
|
file.flush()
|
|
.await
|
|
.map_err(|e| format!("Failed to flush: {}", e))?;
|
|
|
|
Ok(())
|
|
})
|
|
})
|
|
}
|
|
|
|
/// Exemple de transformer qui compte les lignes et ajoute des numéros
|
|
fn create_line_number_transformer() -> StreamTransformer {
|
|
Box::new(|input, mut file, context| {
|
|
Box::pin(async move {
|
|
let mut stream = input.into_byte_stream();
|
|
let mut line_number = 1u32;
|
|
let mut buffer = Vec::new();
|
|
let mut total_written = 0u64;
|
|
|
|
while let Some(chunk_result) = stream.next().await {
|
|
let chunk = chunk_result?;
|
|
buffer.extend_from_slice(&chunk);
|
|
|
|
// Traiter les lignes complètes dans le buffer
|
|
while let Some(newline_pos) = buffer.iter().position(|&b| b == b'\n') {
|
|
let line = &buffer[..newline_pos];
|
|
|
|
// Écrire le numéro de ligne et la ligne
|
|
let numbered_line = format!("{:6}: ", line_number);
|
|
file.write_all(numbered_line.as_bytes())
|
|
.await
|
|
.map_err(|e| format!("Failed to write: {}", e))?;
|
|
|
|
file.write_all(line)
|
|
.await
|
|
.map_err(|e| format!("Failed to write: {}", e))?;
|
|
|
|
file.write_all(b"\n")
|
|
.await
|
|
.map_err(|e| format!("Failed to write: {}", e))?;
|
|
|
|
total_written += numbered_line.len() as u64 + line.len() as u64 + 1;
|
|
context.report_progress(total_written);
|
|
|
|
line_number += 1;
|
|
buffer.drain(..=newline_pos);
|
|
}
|
|
}
|
|
|
|
// Traiter la dernière ligne si elle n'a pas de newline
|
|
if !buffer.is_empty() {
|
|
let numbered_line = format!("{:6}: ", line_number);
|
|
file.write_all(numbered_line.as_bytes())
|
|
.await
|
|
.map_err(|e| format!("Failed to write: {}", e))?;
|
|
|
|
file.write_all(&buffer)
|
|
.await
|
|
.map_err(|e| format!("Failed to write: {}", e))?;
|
|
|
|
total_written += numbered_line.len() as u64 + buffer.len() as u64;
|
|
context.report_progress(total_written);
|
|
}
|
|
|
|
file.flush()
|
|
.await
|
|
.map_err(|e| format!("Failed to flush: {}", e))?;
|
|
|
|
Ok(())
|
|
})
|
|
})
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
println!("=== Exemples de transformers pour le module download ===\n");
|
|
|
|
let temp_dir = std::env::temp_dir();
|
|
|
|
// Exemple 1: Téléchargement avec transformation en majuscules
|
|
println!("1. Téléchargement avec transformation en MAJUSCULES");
|
|
let uppercase_file = temp_dir.join("uppercase_example.txt");
|
|
let _ = std::fs::remove_file(&uppercase_file);
|
|
|
|
let transformer = create_uppercase_transformer();
|
|
let dl = download_with_transformer(
|
|
&uppercase_file,
|
|
"https://www.rust-lang.org/",
|
|
Some(transformer),
|
|
);
|
|
|
|
println!(" Téléchargement démarré...");
|
|
match dl.wait_until_finished().await {
|
|
Ok(_) => {
|
|
println!(" ✓ Téléchargement terminé!");
|
|
println!(" - Taille source: {} bytes", dl.current_size().await);
|
|
println!(
|
|
" - Taille transformée: {} bytes",
|
|
dl.transformed_size().await
|
|
);
|
|
}
|
|
Err(e) => {
|
|
eprintln!(" ✗ Erreur: {}", e);
|
|
}
|
|
}
|
|
|
|
// Exemple 2: Skip header
|
|
println!("\n2. Téléchargement en sautant les 100 premiers bytes");
|
|
let skip_file = temp_dir.join("skip_header_example.txt");
|
|
let _ = std::fs::remove_file(&skip_file);
|
|
|
|
let transformer = create_skip_header_transformer(100);
|
|
let dl = download_with_transformer(&skip_file, "https://www.rust-lang.org/", Some(transformer));
|
|
|
|
match dl.wait_until_finished().await {
|
|
Ok(_) => {
|
|
println!(" ✓ Téléchargement terminé!");
|
|
println!(
|
|
" - Taille transformée: {} bytes",
|
|
dl.transformed_size().await
|
|
);
|
|
}
|
|
Err(e) => {
|
|
eprintln!(" ✗ Erreur: {}", e);
|
|
}
|
|
}
|
|
|
|
// Exemple 3: Numérotation des lignes
|
|
println!("\n3. Téléchargement avec numérotation des lignes");
|
|
let numbered_file = temp_dir.join("numbered_example.txt");
|
|
let _ = std::fs::remove_file(&numbered_file);
|
|
|
|
let transformer = create_line_number_transformer();
|
|
let dl = download_with_transformer(
|
|
&numbered_file,
|
|
"https://www.rust-lang.org/",
|
|
Some(transformer),
|
|
);
|
|
|
|
match dl.wait_until_finished().await {
|
|
Ok(_) => {
|
|
println!(" ✓ Téléchargement terminé!");
|
|
println!(
|
|
" - Taille transformée: {} bytes",
|
|
dl.transformed_size().await
|
|
);
|
|
}
|
|
Err(e) => {
|
|
eprintln!(" ✗ Erreur: {}", e);
|
|
}
|
|
}
|
|
|
|
println!("\n=== Exemples terminés ===");
|
|
println!("Fichiers créés dans: {:?}", temp_dir);
|
|
|
|
// Note: Commenté car nécessite la dépendance async-compression
|
|
/*
|
|
println!("\n4. Téléchargement avec compression GZIP");
|
|
let gzip_file = temp_dir.join("compressed_example.gz");
|
|
let _ = std::fs::remove_file(&gzip_file);
|
|
|
|
let transformer = create_gzip_transformer();
|
|
let dl = download_with_transformer(
|
|
&gzip_file,
|
|
"https://www.rust-lang.org/",
|
|
Some(transformer),
|
|
);
|
|
|
|
match dl.wait_until_finished().await {
|
|
Ok(_) => {
|
|
println!(" ✓ Téléchargement terminé!");
|
|
println!(" - Taille source: {} bytes", dl.current_size().await);
|
|
println!(" - Taille compressée: {} bytes", dl.transformed_size().await);
|
|
let ratio = 100.0 * dl.transformed_size().await as f64 / dl.current_size().await as f64;
|
|
println!(" - Ratio de compression: {:.1}%", ratio);
|
|
}
|
|
Err(e) => {
|
|
eprintln!(" ✗ Erreur: {}", e);
|
|
}
|
|
}
|
|
*/
|
|
}
|