use std::path::PathBuf;
use std::collections::HashMap;
#[cfg(feature = "download")]
use std::fs;
#[cfg(feature = "download")]
use std::io::Write;
#[cfg(feature = "download")]
pub fn get_cache_dir() -> Result<PathBuf, Box<dyn std::error::Error>> {
let home_dir = dirs::home_dir()
.ok_or("Could not find home directory")?;
let cache_dir = home_dir.join(".cache").join("materials_for_mc");
if !cache_dir.exists() {
fs::create_dir_all(&cache_dir)?;
}
Ok(cache_dir)
}
fn get_keyword_url_mapping() -> HashMap<&'static str, &'static str> {
let mut map = HashMap::new();
map.insert("tendl-21", "https://raw.githubusercontent.com/fusion-neutronics/cross_section_data_tendl_2021/refs/heads/main/tendl_2021/");
map.insert("fendl-3.2c", "https://raw.githubusercontent.com/fusion-neutronics/cross_section_data_fendl_3.2c/refs/heads/main/fendl3.2c_data/");
map
}
pub fn is_keyword(input: &str) -> bool {
get_keyword_url_mapping().contains_key(input)
}
#[cfg(feature = "download")]
pub fn expand_keyword_to_url(keyword: &str, nuclide_name: &str) -> Option<String> {
get_keyword_url_mapping()
.get(keyword)
.map(|stem| format!("{}{}.json", stem, nuclide_name))
}
#[cfg(feature = "download")]
fn generate_cache_filename(source: &str, nuclide_name: &str) -> String {
if is_keyword(source) {
format!("{}-{}.json", source, nuclide_name)
} else {
format!("{}.json", nuclide_name)
}
}
#[cfg(feature = "download")]
pub fn download_and_cache(url: &str, source: &str, nuclide_name: &str) -> Result<PathBuf, Box<dyn std::error::Error>> {
let cache_dir = get_cache_dir()?;
let filename = generate_cache_filename(source, nuclide_name);
let local_path = cache_dir.join(filename);
if local_path.exists() {
return Ok(local_path);
}
println!("Downloading URL to cache: {} -> {:?}", url, local_path);
let response = reqwest::blocking::get(url)?;
if !response.status().is_success() {
return Err(format!("Failed to download {}: {}", url, response.status()).into());
}
let content = response.bytes()?;
let mut file = fs::File::create(&local_path)?;
file.write_all(&content)?;
Ok(local_path)
}
pub fn is_url(path_or_url: &str) -> bool {
path_or_url.starts_with("http://") || path_or_url.starts_with("https://")
}
#[cfg(feature = "download")]
pub fn resolve_path_or_url(path_url_or_keyword: &str, nuclide_name: &str) -> Result<PathBuf, Box<dyn std::error::Error>> {
if is_keyword(path_url_or_keyword) {
let url = expand_keyword_to_url(path_url_or_keyword, nuclide_name)
.ok_or_else(|| format!("Unknown keyword: {}", path_url_or_keyword))?;
download_and_cache(&url, path_url_or_keyword, nuclide_name)
} else if is_url(path_url_or_keyword) {
download_and_cache(path_url_or_keyword, path_url_or_keyword, nuclide_name)
} else {
Ok(PathBuf::from(path_url_or_keyword))
}
}
#[cfg(not(feature = "download"))]
pub fn resolve_path_or_url(path_url_or_keyword: &str, _nuclide_name: &str) -> Result<PathBuf, Box<dyn std::error::Error>> {
if is_keyword(path_url_or_keyword) {
return Err("URL downloading and keywords are not supported in WASM builds. Please use local file paths.".into());
} else if is_url(path_url_or_keyword) {
return Err("URL downloading is not supported in WASM builds. Please use local file paths.".into());
} else {
Ok(PathBuf::from(path_url_or_keyword))
}
}