opendp_tooling/proven/
filesystem.rs1use std::{collections::HashMap, env, ffi::OsStr, path::PathBuf};
2
3use darling::{Error, Result};
4use regex::Regex;
5
6pub fn find_proof_paths(
9 src_dir: &std::path::Path,
10) -> std::io::Result<HashMap<String, Option<String>>> {
11 let mut proof_paths = HashMap::new();
12 find_unique_file_names_with_extension(&mut proof_paths, &OsStr::new("tex"), src_dir, src_dir)?;
13 Ok(proof_paths)
14}
15
16pub fn write_proof_paths(proof_paths: &HashMap<String, Option<String>>) -> Result<()> {
18 std::fs::write(
19 get_out_dir()?.join("proof_paths.json"),
20 serde_json::to_string(proof_paths).map_err(Error::custom)?,
21 )
22 .map_err(Error::custom)
23}
24
25pub fn load_proof_paths() -> Result<HashMap<String, Option<String>>> {
28 serde_json::from_str(
29 &std::fs::read_to_string(get_out_dir()?.join("proof_paths.json")).map_err(Error::custom)?,
30 )
31 .map_err(Error::custom)
32}
33
34fn find_unique_file_names_with_extension(
36 matches: &mut HashMap<String, Option<String>>,
37 file_extension: &OsStr,
38 root_dir: &std::path::Path,
39 dir: &std::path::Path,
40) -> std::io::Result<()> {
41 if dir.is_dir() {
42 for entry in std::fs::read_dir(dir)? {
43 let path = entry?.path();
44 if path.is_dir() {
45 find_unique_file_names_with_extension(matches, file_extension, root_dir, &path)?;
46 } else {
47 if path.extension() != Some(file_extension) {
48 continue;
49 }
50 if let Some(file_name) = path.file_stem() {
51 matches
52 .entry(file_name.to_string_lossy().to_string())
53 .and_modify(|v| drop(v.take()))
55 .or_insert_with(|| {
56 Some(
57 path.strip_prefix(root_dir)
58 .expect("unreachable")
59 .to_string_lossy()
60 .to_string(),
61 )
62 });
63 }
64 };
65 }
66 }
67 Ok(())
68}
69
70pub fn get_src_dir() -> Result<PathBuf> {
71 let manifest_dir = std::env::var_os("CARGO_MANIFEST_DIR")
72 .ok_or_else(|| Error::custom("Failed to determine location of Cargo.toml."))?;
73 Ok(PathBuf::from(manifest_dir).join("src"))
74}
75
76fn get_out_dir() -> Result<PathBuf> {
77 let manifest_dir =
78 std::env::var_os("OUT_DIR").ok_or_else(|| Error::custom("Failed to determine OUT_DIR."))?;
79 Ok(PathBuf::from(manifest_dir))
80}
81
82pub fn make_proof_link(
83 source_dir: PathBuf,
84 mut relative_path: PathBuf,
85 repo_path: PathBuf,
86) -> Result<String> {
87 let absolute_path = source_dir.join(&relative_path);
89
90 if !absolute_path.exists() {
91 return Err(Error::custom(format!("{absolute_path:?} does not exist!")));
92 }
93
94 relative_path.set_extension("pdf");
96
97 let proof_uri = if let Ok(sphinx_port) = env::var("OPENDP_SPHINX_PORT") {
99 format!("http://localhost:{sphinx_port}")
100 } else {
101 let docs_uri = env::var("OPENDP_REMOTE_SPHINX_URI")
103 .unwrap_or_else(|_| "https://docs.opendp.org".to_string());
104
105 let version = env!("CARGO_PKG_VERSION");
107 let docs_ref = get_docs_ref(version);
108
109 format!("{docs_uri}/en/{docs_ref}")
110 };
111
112 Ok(format!(
113 "{proof_uri}/proofs/{repo_path}/{relative_path}",
114 proof_uri = proof_uri,
115 repo_path = repo_path.display(),
116 relative_path = relative_path.display()
117 ))
118}
119
120fn get_docs_ref(version: &str) -> String {
121 let channel = get_channel(version);
123 match channel.as_str() {
124 "stable" => format!("v{version}"), "dev" => "nightly".to_string(), _ => channel, }
128}
129
130fn get_channel(version: &str) -> String {
131 let re = Regex::new(r"^(\d+\.\d+\.\d+)(?:-(dev|nightly|beta)(?:\.(.+))?)?$").unwrap();
132 if let Some(caps) = re.captures(version) {
133 let channel = caps.get(2);
134 return channel.map_or("stable", |m| m.as_str()).to_string();
135 }
136 "unknown".to_string()
137}