hematite-kokoros 0.1.2

Hematite-maintained fork of the Kokoros Rust text-to-speech engine
Documentation
use indicatif::{ProgressBar, ProgressStyle};
use serde_json::Value;
use std::io::Read;
use tokio::{fs::File, io::AsyncWriteExt};
use reqwest;

pub async fn download_file_from_url(
    url: &str,
    path: &str,
) -> Result<(), Box<dyn std::error::Error>> {
    let res = reqwest::get(url).await?;
    let total_size = res
        .content_length()
        .ok_or_else(|| format!("Failed to get content length from '{}'", url))?;

    let pb = ProgressBar::new(total_size);
    pb.set_style(ProgressStyle::default_bar()
        .template("{msg}\n{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})")
        .unwrap()
        .progress_chars("#>-"));
    pb.set_message(format!("Downloading {}", path));

    let mut file = File::create(path).await?;
    let mut downloaded: u64 = 0;
    let mut stream = res.bytes_stream();

    use futures_util::StreamExt;
    while let Some(item) = stream.next().await {
        let chunk = item?;
        file.write_all(&chunk).await?;
        let new = std::cmp::min(downloaded + (chunk.len() as u64), total_size);
        downloaded = new;
        pb.set_position(new);
    }

    pb.finish_with_message(format!("Downloaded {} to {}", url, path));
    Ok(())
}

pub fn read_json_file(path: &str) -> Result<Value, Box<dyn std::error::Error>> {
    let mut file = std::fs::File::open(path)?;
    let mut content = String::new();
    file.read_to_string(&mut content)?;
    let json: Value = serde_json::from_str(&content)?;
    Ok(json)
}