use std::path::Path; use std::path::PathBuf; #[cfg(feature = "tokio")] use tokio::task; #[cfg(feature = "async-std")] use async_std::task; use futures::stream::StreamExt; use clap::Parser; use unrar_async::Archive; #[derive(Debug, Parser)] struct Options { /// List of rar files to process #[clap(required = true, num_args = 1..)] rar_file: Vec, } /// This is the "real" entrypoint; the main() functions below are just thin wrappers that the different executors can utilize async fn run() { let options = Options::parse(); let mut futures = Vec::new(); for file in options.rar_file { futures.push(task::spawn(async move { let mut lines = vec![format!("--- {}", file.display())]; lines.extend(process(&file).await.unwrap()); lines.push("".into()); println!("{}", lines.join("\n")); })); } futures::future::join_all(futures).await; } async fn process(rar_file: &Path) -> anyhow::Result> { let mut lines = Vec::new(); match Archive::new(rar_file).unwrap().list_split().await { Ok(mut archive) => { while let Some(entry) = archive.next().await { match entry { Ok(entry) => lines.push(entry.to_string()), Err(e) => lines.push(format!("Error: {}", e)) }; } }, // Irrecoverable failure, do nothing. Err(e) => eprintln!("Error: {}", e) } Ok(lines) } #[cfg(feature = "tokio")] #[tokio::main] async fn main() { run().await } #[cfg(feature = "async-std")] #[async_std::main] async fn main() { run().await }