use std::path::{Path, PathBuf};
use sha2::{Digest, Sha256};
pub fn cache_dir() -> Option<PathBuf> {
let mut p = dirs::cache_dir()?;
p.push("outl");
p.push("runtimes");
std::fs::create_dir_all(&p).ok()?;
Some(p)
}
pub fn cache_path_for_source(language: &str, source: &str) -> Option<PathBuf> {
let mut dir = cache_dir()?;
dir.push(language);
std::fs::create_dir_all(&dir).ok()?;
let mut hasher = Sha256::new();
hasher.update(source.as_bytes());
let digest = hasher.finalize();
let mut hash = String::with_capacity(digest.len() * 2);
for b in digest {
use std::fmt::Write;
let _ = write!(hash, "{b:02x}");
}
dir.push(format!("{hash}.wasm"));
Some(dir)
}
pub fn is_fresh(path: &Path) -> bool {
std::fs::metadata(path)
.map(|m| m.is_file() && m.len() > 0)
.unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cache_dir_exists_or_returns_none() {
let _ = cache_dir();
}
#[test]
fn same_source_hashes_to_same_path() {
let a = cache_path_for_source("rust", "fn main() {}").unwrap();
let b = cache_path_for_source("rust", "fn main() {}").unwrap();
assert_eq!(a, b);
}
#[test]
fn different_sources_hash_differently() {
let a = cache_path_for_source("rust", "fn main() {}").unwrap();
let b = cache_path_for_source("rust", "fn main() { 1; }").unwrap();
assert_ne!(a, b);
}
}