use s_zip::{AsyncStreamingZipWriter, GenericAsyncZipReader};
use std::io::Cursor;
use tokio::io::AsyncReadExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ Reading ZIP Files from HTTP Sources ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
println!("📦 Step 1: Creating a test ZIP file in memory...\n");
let zip_bytes = create_test_zip_in_memory().await?;
println!(" Created {} bytes ZIP in memory\n", zip_bytes.len());
println!("🌐 Step 2: Reading ZIP from in-memory source (simulating HTTP)...\n");
let cursor = Cursor::new(zip_bytes.clone());
let mut reader = GenericAsyncZipReader::new(cursor).await?;
println!(" ✓ Successfully opened ZIP from in-memory source\n");
println!("📋 Step 3: Listing entries in the ZIP:\n");
for (idx, entry) in reader.entries().iter().enumerate() {
println!(
" [{}] {} - {} bytes (compressed: {} bytes)",
idx, entry.name, entry.uncompressed_size, entry.compressed_size
);
}
println!();
println!("📖 Step 4: Reading specific entries:\n");
if let Ok(data) = reader.read_entry_by_name("readme.txt").await {
println!(" readme.txt content:");
println!(" {}\n", String::from_utf8_lossy(&data));
}
if let Ok(data) = reader.read_entry_by_name("data.json").await {
println!(" data.json content:");
println!(" {}\n", String::from_utf8_lossy(&data));
}
println!("🌊 Step 5: Streaming large file without loading to memory:\n");
if let Ok(mut stream) = reader.read_entry_streaming_by_name("large.bin").await {
let mut buffer = vec![0u8; 4096];
let mut total_bytes = 0u64;
let mut chunks = 0;
loop {
let n = stream.read(&mut buffer).await?;
if n == 0 {
break;
}
total_bytes += n as u64;
chunks += 1;
}
println!(" Streamed {} bytes in {} chunks\n", total_bytes, chunks);
}
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ Real HTTP Example ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
println!("To read from actual HTTP source:");
println!("```rust");
println!("use reqwest;");
println!("use std::io::Cursor;");
println!();
println!("// Download ZIP into memory");
println!("let response = reqwest::get(\"https://example.com/file.zip\").await?;");
println!("let bytes = response.bytes().await?;");
println!("let cursor = Cursor::new(bytes.to_vec());");
println!();
println!("// Read ZIP from memory");
println!("let mut reader = GenericAsyncZipReader::new(cursor).await?;");
println!("let data = reader.read_entry_by_name(\"file.txt\").await?;");
println!("```\n");
println!("✅ Example completed successfully!\n");
Ok(())
}
async fn create_test_zip_in_memory() -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let buffer = Vec::new();
let cursor = Cursor::new(buffer);
let mut writer = AsyncStreamingZipWriter::from_writer(cursor);
writer.start_entry("readme.txt").await?;
writer
.write_data(b"This is a test ZIP file created in memory.")
.await?;
writer.start_entry("data.json").await?;
writer
.write_data(br#"{"name": "test", "value": 42, "status": "ok"}"#)
.await?;
writer.start_entry("large.bin").await?;
let data = vec![0xAB; 50_000]; writer.write_data(&data).await?;
writer.start_entry("info.txt").await?;
writer
.write_data(b"Additional information stored in the archive.")
.await?;
let cursor = writer.finish().await?;
Ok(cursor.into_inner())
}