nornir 0.4.34

Companion to cargo: dependency tracking, release gating, deploy, benchmarks, and documentation assembly. Project-agnostic.
//! Reusable bench fixtures and asset downloader.
//!
//! Core types ([`MavenAsset`], [`ensure`], [`default_cache_dir`]) are
//! project-agnostic. The canonical Maven Central JAR set
//! ([`BENCH_JARS`]) is gated behind the `fixtures-maven` feature so
//! the core library ships no project-specific data.

use std::fs;
use std::io::Read;
use std::path::PathBuf;

const MAVEN_BASE: &str = "https://repo1.maven.org/maven2";

#[derive(Debug, Clone, Copy)]
pub struct MavenAsset {
    pub filename: &'static str,
    pub maven_path: &'static str,
    pub label: &'static str,
}

/// Default on-disk cache. Honours `NORNIR_BENCH_CACHE` if set, else
/// `$HOME/.cache/nornir/bench-assets`.
pub fn default_cache_dir() -> PathBuf {
    if let Ok(d) = std::env::var("NORNIR_BENCH_CACHE") {
        return PathBuf::from(d);
    }
    let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
    PathBuf::from(home).join(".cache/nornir/bench-assets")
}

/// Ensure the asset exists in `cache_dir`, downloading via the pure-Rust
/// `ureq` HTTP client if missing. Returns `None` if the download failed
/// (caller decides whether to skip or fail).
pub fn ensure(asset: &MavenAsset, cache_dir: &std::path::Path) -> Option<PathBuf> {
    fs::create_dir_all(cache_dir).ok()?;
    let path = cache_dir.join(asset.filename);
    if path.exists() {
        return Some(path);
    }
    let url = format!("{}/{}", MAVEN_BASE, asset.maven_path);
    eprintln!("  downloading {} ...", asset.filename);
    let resp = ureq::get(&url).call().ok()?;
    if resp.status() != 200 {
        return None;
    }
    let mut buf = Vec::new();
    resp.into_reader().read_to_end(&mut buf).ok()?;
    let tmp = path.with_extension("part");
    fs::write(&tmp, &buf).ok()?;
    fs::rename(&tmp, &path).ok()?;
    Some(path)
}

/// Canonical Maven Central JAR fixtures: a mix of small and large
/// real-world archives suitable for decompression benchmarks. Opt in
/// with `features = ["fixtures-maven"]`.
#[cfg(feature = "fixtures-maven")]
pub const BENCH_JARS: &[MavenAsset] = &[
    MavenAsset {
        filename: "guava-33.2.1-jre.jar",
        maven_path: "com/google/guava/guava/33.2.1-jre/guava-33.2.1-jre.jar",
        label: "guava_3.4MB",
    },
    MavenAsset {
        filename: "ecj-3.37.0.jar",
        maven_path: "org/eclipse/jdt/ecj/3.37.0/ecj-3.37.0.jar",
        label: "ecj_4.8MB",
    },
    MavenAsset {
        filename: "scala-library-2.13.14.jar",
        maven_path: "org/scala-lang/scala-library/2.13.14/scala-library-2.13.14.jar",
        label: "scala_5.8MB",
    },
    MavenAsset {
        filename: "kotlin-stdlib-2.0.0.jar",
        maven_path: "org/jetbrains/kotlin/kotlin-stdlib/2.0.0/kotlin-stdlib-2.0.0.jar",
        label: "kotlin_1.8MB",
    },
];