98335f435d
type: added
56 lines
1.2 KiB
Rust
56 lines
1.2 KiB
Rust
use crate::common::*;
|
|
|
|
use std::path::Component;
|
|
|
|
pub(crate) trait PathExt {
|
|
fn clean(self) -> PathBuf;
|
|
}
|
|
|
|
impl PathExt for &Path {
|
|
fn clean(self) -> PathBuf {
|
|
let mut components = Vec::new();
|
|
|
|
for component in self.components() {
|
|
if component == Component::ParentDir {
|
|
if let Some(Component::Normal(_)) = components.last() {
|
|
components.pop();
|
|
}
|
|
} else {
|
|
components.push(component);
|
|
}
|
|
}
|
|
|
|
components.into_iter().collect()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn clean() {
|
|
let cases = &[
|
|
("/", "foo", "/foo"),
|
|
("/", ".", "/"),
|
|
("/", "foo/./bar", "/foo/bar"),
|
|
("/foo/./bar", ".", "/foo/bar"),
|
|
("/bar", "/foo", "/foo"),
|
|
("//foo", "bar//baz", "/foo/bar/baz"),
|
|
("/", "..", "/"),
|
|
("/", "/..", "/"),
|
|
("/..", "", "/"),
|
|
("/../../../..", "../../../", "/"),
|
|
("/.", "./", "/"),
|
|
("/foo/../", "bar", "/bar"),
|
|
("/foo/bar", "..", "/foo"),
|
|
("/foo/bar/", "..", "/foo"),
|
|
];
|
|
|
|
for (prefix, suffix, want) in cases {
|
|
let have = Path::new(prefix).join(Path::new(suffix)).clean();
|
|
assert_eq!(have, Path::new(want));
|
|
}
|
|
}
|
|
}
|