feat(async): use async i/o with tokio

This commit is contained in:
2025-07-14 22:16:07 +02:00
parent ec25edc81a
commit 72b8174422
3 changed files with 586 additions and 389 deletions

900
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,8 @@ authors = ["Chouhartem <fabrice.mouhartem@epheme.re>"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
async_zip = { version = "0.0.17", features = ["full"] }
infer = "0.16.0" infer = "0.16.0"
magick_rust = "1.0.0" magick_rust = "1.0.0"
zip = "2.1.6" tokio = { version = "1.46.1", features = ["full"] }
tokio-util = { version = "0.7.15", features = ["full"] }

View File

@ -1,36 +1,57 @@
use async_zip;
use async_zip::base::read::seek::ZipFileReader;
use async_zip::base::write::ZipFileWriter;
use async_zip::{Compression, ZipEntryBuilder};
use infer; use infer;
use magick_rust; use magick_rust;
use std::env; use std::env;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs::File;
use std::io::prelude::*;
use std::io::Write;
use std::path::Path; use std::path::Path;
use zip; use tokio::{
use zip::write::SimpleFileOptions; fs::File,
io::BufReader,
};
use tokio_util::compat::{TokioAsyncReadCompatExt };
#[tokio::main]
fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
let mut argv = env::args(); let mut argv = env::args();
if argv.len() != 2 { if argv.len() != 2 {
panic!("Not enough arguments"); panic!("Not enough arguments");
} }
let filename: String = argv.nth(1).unwrap(); let filename: String = argv.nth(1).unwrap();
let buf = File::open(&filename)?; let buf = File::open(&filename)
.await
.expect("Failed to open input file.");
magick_rust::magick_wand_genesis(); magick_rust::magick_wand_genesis();
let mut zip = zip::ZipArchive::new(buf)?; let buf = BufReader::new(buf).compat();
let mut zip = ZipFileReader::new(buf)
.await
.expect("Failed to decompress input file.");
let tmp_filename = filename.to_string() + ".tmp"; let tmp_filename = filename.to_string() + ".tmp";
let mut tmp_file = File::create(tmp_filename)?; let tmp_filepath = Path::new(&tmp_filename);
let mut tmp_zip = zip::ZipWriter::new(&mut tmp_file); let tmp_file = File::create(tmp_filepath).await?;
let options = SimpleFileOptions::default(); let mut tmp_zip = ZipFileWriter::new(tmp_file.compat());
for i in 0..zip.len() { for i in 0..zip.file().entries().len() {
let mut file = zip.by_index(i)?; let file = zip.file().entries().get(i).unwrap().clone();
let mut buf = Vec::new(); let filename = file.filename();
let n = file.read_to_end(&mut buf)?; let mut entry = zip
.reader_with_entry(i)
.await
.expect("Failed to get zip individual file.");
let mut buf = vec![];
let n = entry
.read_to_end_checked(&mut buf)
.await
.expect("Failed to read the zip individual file.");
if infer::is_image(&buf[..n]) { if infer::is_image(&buf[..n]) {
let extension = Path::new(file.name()).extension().and_then(OsStr::to_str).expect("String"); let extension = Path::new(filename.as_str().expect("Failed to read filename."))
.extension()
.and_then(OsStr::to_str)
.expect("String");
println!("{}", extension); println!("{}", extension);
let wand = magick_rust::MagickWand::new(); let wand = magick_rust::MagickWand::new();
wand.read_image_blob(buf).expect("Successful read"); wand.read_image_blob(buf).expect("Successful read");
@ -38,15 +59,21 @@ fn main() -> std::io::Result<()> {
wand.strip_image().expect("Strip"); wand.strip_image().expect("Strip");
let to_write = wand.write_image_blob(extension).expect("Write worked"); let to_write = wand.write_image_blob(extension).expect("Write worked");
println!("data len: {}", to_write.len()); println!("data len: {}", to_write.len());
tmp_zip.start_file(file.name(), options)?; let builder = ZipEntryBuilder::new(filename.clone(), Compression::Deflate);
tmp_zip.write_all(&to_write)?; tmp_zip
.write_entry_whole(builder, &to_write)
.await
.expect("Failed to write a compressed image.");
} else { } else {
tmp_zip.start_file(file.name(), options)?; let builder = ZipEntryBuilder::new(filename.clone(), Compression::Deflate);
tmp_zip.write_all(&buf)?; tmp_zip
.write_entry_whole(builder, &buf)
.await
.expect("Failed to write a normal file??");
} }
} }
tmp_zip.finish()?; tmp_zip.close().await.expect("Failed to close the file");
Ok(()) Ok(())
} }