use std::path::{Component, Path, PathBuf};
#[must_use]
pub fn join_lexical(base: &Path, path: &Path) -> PathBuf {
let mut joined = PathBuf::new();
for component in base.components().chain(path.components()) {
match component {
Component::ParentDir if joined.pop() => {}
other => joined.push(other),
}
}
joined
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn join_lexical_resolves_parent_segments() {
let cases = [
("/r/tools/a", "../../../etc/skif.toml", "/etc/skif.toml"),
("/r", "../etc/skif.toml", "/etc/skif.toml"),
("/r/tools/a", "", "/r/tools/a"),
("a/b", "package.json", "a/b/package.json"),
("a", "../skif.toml", "skif.toml"),
("", "x", "x"),
("", "../skif.toml", "../skif.toml"),
];
for (base, path, expected) in cases {
assert_eq!(
join_lexical(Path::new(base), Path::new(path)),
Path::new(expected),
"{base} + {path}"
);
}
}
}