ugi 0.2.1

Runtime-agnostic Rust request client with HTTP/1.1, HTTP/2, HTTP/3, H2C, WebSocket, SSE, and gRPC support
Documentation
//! Parallel file download with optional integrity verification and rate limiting.
//!
//! Run with:
//!   cargo run --example download

use std::path::Path;

use futures_lite::future::block_on;
use ugi::{Client, RateLimiter, download::HashAlgorithm};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    block_on(async move {
        let client = Client::builder().build()?;

        // ── 1. Simple single-stream download ────────────────────────────────
        let result = client
            .download("https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso")
            .save(Path::new("/tmp/ubuntu.iso"))
            .await?;

        println!(
            "downloaded {} bytes in {} chunk(s)",
            result.total_bytes, result.chunks_used
        );

        // ── 2. Parallel chunks + SHA-256 integrity check ─────────────────────
        let checksum = "45f873de9f8cb637345d6e66a583762730bbea30277ef7b32c9c3bd6700a32b2";
        client
            .download("https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso")
            .chunks(8)
            .verify(HashAlgorithm::Sha256, checksum)
            .save(Path::new("/tmp/ubuntu-verified.iso"))
            .await?;

        println!("integrity verified");

        // ── 3. Probe only — inspect server capabilities without downloading ──
        let caps = client
            .download("https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso")
            .probe()
            .await?;

        println!(
            "size: {:?}, range: {}, etag: {:?}",
            caps.content_length, caps.supports_range, caps.etag
        );

        // ── 4. Shared rate limiter across concurrent downloads ───────────────
        let limiter = RateLimiter::new(4 * 1024 * 1024); // 4 MB/s total budget

        let d1 = client
            .download("https://example.com/file-a.bin")
            .rate_limit_shared(limiter.clone())
            .save(Path::new("/tmp/file-a.bin"));

        let d2 = client
            .download("https://example.com/file-b.bin")
            .rate_limit_shared(limiter.clone())
            .save(Path::new("/tmp/file-b.bin"));

        // Drive both concurrently; both share the 4 MB/s ceiling.
        let (r1, r2) = futures_lite::future::zip(d1, d2).await;
        println!("a: {} bytes, b: {} bytes", r1?.total_bytes, r2?.total_bytes);

        Ok(())
    })
}