quilt-rs 0.14.0

Rust library for accessing Quilt data packages.
Documentation
use std::path::PathBuf;

use async_stream::stream;
use multihash::Multihash;
use tracing::log;

use quilt_rs::manifest::Row;

use crate::cli::model::Commands;
use crate::cli::output::Std;
use crate::cli::Error;
use crate::perf::Measure;

#[derive(Debug)]
pub struct Input {
    pub dest_dir: PathBuf,
    pub number: i32,
}

pub struct Output {
    pub dest: PathBuf,
    pub perf: Measure,
    pub top_hash: String,
}

impl std::fmt::Display for Output {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut output: Vec<String> = Vec::new();
        output.push(format!("Manifest written to {:?}", &self.dest));
        output.push(format!("With hash {}", &self.top_hash));
        output.push(format!("And it took {}", &self.perf.elapsed()));
        write!(f, "{}", output.join("\n"))
    }
}

pub async fn command(m: impl Commands, args: Input) -> Std {
    Std::from_result(m.benchmark(args).await)
}

async fn benchmark(
    local_domain: &quilt_rs::LocalDomain,
    dest: PathBuf,
    number: i32,
) -> Result<(PathBuf, String), Error> {
    let mut i = 0;
    let stream = stream! {
        let mut chunk = Vec::new();
        while i < number {
            let name = PathBuf::from(format!("file://{}", i));
            let row= Row {
                name,
                hash: Multihash::wrap(0xb510, b"pedestrian").expect("Unexpected"),
                ..Row::default()
            };
            chunk.push(Ok(row));

            if (i > 0 && i % 100_000 == 0) || (i == number -1) {
                yield(Ok(chunk));
                chunk = vec![];
            }

            if i > 0 && i % 10_000 == 0 && i < 100_000 {
                log::debug!("Another 10k rows written, {}", i);
            }
            if i > 0 && i % 100_000 == 0 && i < 1_000_000 {
                log::debug!("Another 100k rows written, {}", i);
            }
            if i > 0 && i % 1_000_000 == 0 {
                log::debug!("Another million rows written, {}", i);
            }
            i += 1;
        }
    };
    Ok(local_domain.build_manifest(dest, Box::pin(stream)).await?)
}

pub async fn model(
    local_domain: &quilt_rs::LocalDomain,
    Input { dest_dir, number }: Input,
) -> Result<Output, Error> {
    let perf = Measure::start();
    let (dest, top_hash) = benchmark(local_domain, dest_dir, number).await?;
    Ok(Output {
        dest,
        perf,
        top_hash,
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_output_display() {
        let dest = PathBuf::from("/path/to/manifest");
        let top_hash = "abc123".to_string();

        let output = Output {
            dest,
            perf: Measure::start(),
            top_hash,
        };

        let display_string = format!("{}", output);
        let expected = "Manifest written to \"/path/to/manifest\"\nWith hash abc123\nAnd it took";
        assert!(display_string.starts_with(expected));
    }
}