use crate::SourceProvider;
use rustyfi_syntax::RustyfiVersion;
use std::path::{Path, PathBuf};
pub(crate) const CANDIDATE_EXTS: [&str; 2] = [".satyh", ".satyg"];
fn has_candidate_ext(name: &str) -> bool {
CANDIDATE_EXTS.iter().any(|ext| name.ends_with(ext))
}
fn candidates_in(base: &Path, name: &str) -> Vec<PathBuf> {
if has_candidate_ext(name) {
vec![base.join(name)]
} else {
CANDIDATE_EXTS
.iter()
.map(|ext| base.join(format!("{name}{ext}")))
.collect()
}
}
pub fn resolve_import(
sources: &dyn SourceProvider,
dir: &Path,
name: &str,
) -> Result<PathBuf, Vec<PathBuf>> {
let candidates = candidates_in(dir, name);
for candidate in &candidates {
if sources.is_file(candidate) {
return Ok(candidate.clone());
}
}
Err(candidates)
}
pub fn resolve_require(
sources: &dyn SourceProvider,
roots: &[&Path],
name: &str,
version: RustyfiVersion,
) -> Result<PathBuf, Vec<PathBuf>> {
let mut searched = Vec::new();
for root in roots {
match resolve_require_in(sources, root, name, version) {
Ok(found) => return Ok(found),
Err(tried) => searched.extend(tried),
}
}
Err(searched)
}
fn resolve_require_in(
sources: &dyn SourceProvider,
root: &Path,
name: &str,
version: RustyfiVersion,
) -> Result<PathBuf, Vec<PathBuf>> {
let dist_packages = root.join("dist").join("packages");
let dist_v01_packages = root.join("dist-v01").join("packages");
let bases: Vec<PathBuf> = if version == RustyfiVersion::V0_1 {
vec![
dist_v01_packages.clone(),
dist_v01_packages.join(name),
dist_packages.clone(),
root.to_path_buf(),
dist_packages.join(name),
]
} else {
vec![
dist_packages.clone(),
root.to_path_buf(),
dist_packages.join(name),
dist_v01_packages.clone(),
dist_v01_packages.join(name),
]
};
let mut candidates = Vec::new();
for base in &bases {
candidates.extend(candidates_in(base, name));
}
for candidate in &candidates {
if sources.is_file(candidate) {
return Ok(candidate.clone());
}
}
Err(candidates)
}