redox_pkgutils 0.1.9

Redox Packaging Utilities
Documentation
use std::fs::File;
use std::io::{self, stderr, Read, Write};
use std::time::Duration;

use reqwest::{
    blocking::Client,
    StatusCode,
};

use pbr::{ProgressBar, Units};

pub fn download_client() -> Client {
    Client::builder()
        .timeout(Duration::new(5, 0))
        .build()
        .unwrap()
}

pub fn download(client: &Client, remote_path: &str, local_path: &str) -> io::Result<()> {
    let mut stderr = stderr();

    write!(stderr, "* Requesting {}\n", remote_path)?;

    let mut response = match client.get(remote_path).send() {
        Ok(response) => response,
        Err(err) => return Err(io::Error::new(io::ErrorKind::Other, err)),
    };

    match response.status() {
        StatusCode::OK => {
            let mut count = 0;
            let length = response.content_length().unwrap_or(0);

            let mut file = File::create(&local_path)?;
            let mut pb = ProgressBar::new(length as u64);
            pb.set_max_refresh_rate(Some(Duration::new(1, 0)));
            pb.set_units(Units::Bytes);
            loop {
                let mut buf = [0; 8192];
                let res = response.read(&mut buf)?;
                if res == 0 {
                    break;
                }
                count += file.write(&buf[..res])?;
                pb.set(count as u64);
            }
            let _ = write!(stderr, "\n");

            file.sync_all()?;

            Ok(())
        }
        _ => {
            let _ = write!(stderr, "* Failure {}\n", response.status());

            Err(io::Error::new(
                io::ErrorKind::NotFound,
                format!("{} not found", remote_path),
            ))
        }
    }
}