use std::{path::Path, process};
use avio::{AsyncImageDecoder, DecodeError};
use futures::future;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut args = std::env::args().skip(1);
let mut inputs: Vec<String> = Vec::new();
while let Some(flag) = args.next() {
match flag.as_str() {
"--input" | "-i" => inputs.push(args.next().unwrap_or_default()),
other => {
eprintln!("Unknown flag: {other}");
process::exit(1);
}
}
}
if inputs.is_empty() {
eprintln!("Usage: async_decode_image --input <file> [--input <file> ...]");
process::exit(1);
}
println!("=== Pattern 1: single async decode ===");
let first = inputs[0].clone();
let file_name = Path::new(&first)
.file_name()
.and_then(|n| n.to_str())
.unwrap_or(&first)
.to_owned();
match AsyncImageDecoder::open(first).await {
Ok(decoder) => match decoder.decode().await {
Ok(frame) => {
println!("File: {file_name}");
println!("Dimensions: {}×{}", frame.width(), frame.height());
println!("Pixel format: {}", frame.format());
println!("Planes: {}", frame.num_planes());
for i in 0..frame.num_planes() {
let stride = frame.stride(i).unwrap_or(0);
let plane_len = frame.plane(i).map_or(0, |p| p.len());
let label = match i {
0 => " (Y)",
1 => " (U)",
2 => " (V)",
_ => "",
};
println!(" plane {i}{label} stride={stride} size={plane_len} bytes");
}
println!("Total size: {} bytes", frame.total_size());
}
Err(e) => eprintln!("Decode error: {e}"),
},
Err(DecodeError::FileNotFound { path }) => eprintln!("File not found: {}", path.display()),
Err(e) => eprintln!("Open error: {e}"),
}
if inputs.len() == 1 {
return Ok(());
}
println!();
println!(
"=== Pattern 2: parallel decode with join_all ({} images) ===",
inputs.len()
);
let decode_futures: Vec<_> = inputs
.iter()
.map(|path| {
let path = path.clone();
async move {
let file_name = Path::new(&path)
.file_name()
.and_then(|n| n.to_str())
.unwrap_or(&path)
.to_owned();
let result = async { AsyncImageDecoder::open(path).await?.decode().await }.await;
(file_name, result)
}
})
.collect();
let results = future::join_all(decode_futures).await;
for (file_name, result) in results {
match result {
Ok(frame) => println!(
" {file_name}: {}×{} format={} total={} bytes",
frame.width(),
frame.height(),
frame.format(),
frame.total_size(),
),
Err(e) => eprintln!(" {file_name}: error — {e}"),
}
}
Ok(())
}