opendp_tooling/proven/
filesystem.rsuse std::{collections::HashMap, env, ffi::OsStr, path::PathBuf};
use darling::{Error, Result};
use regex::Regex;
pub fn find_proof_paths(
src_dir: &std::path::Path,
) -> std::io::Result<HashMap<String, Option<String>>> {
let mut proof_paths = HashMap::new();
find_unique_file_names_with_extension(&mut proof_paths, &OsStr::new("tex"), src_dir, src_dir)?;
Ok(proof_paths)
}
pub fn write_proof_paths(proof_paths: &HashMap<String, Option<String>>) -> Result<()> {
std::fs::write(
get_out_dir()?.join("proof_paths.json"),
serde_json::to_string(proof_paths).map_err(Error::custom)?,
)
.map_err(Error::custom)
}
pub fn load_proof_paths() -> Result<HashMap<String, Option<String>>> {
serde_json::from_str(
&std::fs::read_to_string(get_out_dir()?.join("proof_paths.json")).map_err(Error::custom)?,
)
.map_err(Error::custom)
}
fn find_unique_file_names_with_extension(
matches: &mut HashMap<String, Option<String>>,
file_extension: &OsStr,
root_dir: &std::path::Path,
dir: &std::path::Path,
) -> std::io::Result<()> {
if dir.is_dir() {
for entry in std::fs::read_dir(dir)? {
let path = entry?.path();
if path.is_dir() {
find_unique_file_names_with_extension(matches, file_extension, root_dir, &path)?;
} else {
if path.extension() != Some(file_extension) {
continue;
}
if let Some(file_name) = path.file_stem() {
matches
.entry(file_name.to_string_lossy().to_string())
.and_modify(|v| drop(v.take()))
.or_insert_with(|| {
Some(
path.strip_prefix(root_dir)
.expect("unreachable")
.to_string_lossy()
.to_string(),
)
});
}
};
}
}
Ok(())
}
pub fn get_src_dir() -> Result<PathBuf> {
let manifest_dir = std::env::var_os("CARGO_MANIFEST_DIR")
.ok_or_else(|| Error::custom("Failed to determine location of Cargo.toml."))?;
Ok(PathBuf::from(manifest_dir).join("src"))
}
fn get_out_dir() -> Result<PathBuf> {
let manifest_dir =
std::env::var_os("OUT_DIR").ok_or_else(|| Error::custom("Failed to determine OUT_DIR."))?;
Ok(PathBuf::from(manifest_dir))
}
pub fn make_proof_link(
source_dir: PathBuf,
mut relative_path: PathBuf,
repo_path: PathBuf,
) -> Result<String> {
let absolute_path = source_dir.join(&relative_path);
if !absolute_path.exists() {
return Err(Error::custom(format!("{absolute_path:?} does not exist!")));
}
relative_path.set_extension("pdf");
let proof_uri = if let Ok(sphinx_port) = env::var("OPENDP_SPHINX_PORT") {
format!("http://localhost:{sphinx_port}")
} else {
let docs_uri = env::var("OPENDP_REMOTE_SPHINX_URI")
.unwrap_or_else(|_| "https://docs.opendp.org".to_string());
let version = env!("CARGO_PKG_VERSION");
let docs_ref = get_docs_ref(version);
format!("{docs_uri}/en/{docs_ref}")
};
Ok(format!(
"{proof_uri}/proofs/{repo_path}/{relative_path}",
proof_uri = proof_uri,
repo_path = repo_path.display(),
relative_path = relative_path.display()
))
}
fn get_docs_ref(version: &str) -> String {
let channel = get_channel(version);
match channel.as_str() {
"stable" => format!("v{version}"), "dev" => "nightly".to_string(), _ => channel, }
}
fn get_channel(version: &str) -> String {
let re = Regex::new(r"^(\d+\.\d+\.\d+)(?:-(dev|nightly|beta)(?:\.(.+))?)?$").unwrap();
if let Some(caps) = re.captures(version) {
let channel = caps.get(2);
return channel.map_or("stable", |m| m.as_str()).to_string();
}
"unknown".to_string()
}