use std::path::{Component, Path, PathBuf};
pub trait NormalizePath {
fn normalize(&self) -> PathBuf;
fn try_normalize(&self) -> Option<PathBuf>;
fn is_normalized(&self) -> bool;
}
impl NormalizePath for Path {
fn normalize(&self) -> PathBuf {
let mut components = self.components().peekable();
let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek() {
let buf = PathBuf::from(c.as_os_str());
components.next();
buf
} else {
PathBuf::new()
};
for component in components {
match component {
Component::Prefix(..) => unreachable!(),
Component::RootDir => {
ret.push(component.as_os_str());
}
Component::CurDir => {}
Component::ParentDir => {
ret.pop();
}
Component::Normal(c) => {
ret.push(c);
}
}
}
ret
}
fn try_normalize(&self) -> Option<PathBuf> {
let mut ret = PathBuf::new();
for component in self.components() {
match component {
Component::Prefix(..) | Component::RootDir => return None,
Component::CurDir => {}
Component::ParentDir => {
if !ret.pop() {
return None;
}
}
Component::Normal(c) => {
ret.push(c);
}
}
}
Some(ret)
}
fn is_normalized(&self) -> bool {
for component in self.components() {
match component {
Component::CurDir | Component::ParentDir => {
return false;
}
_ => continue,
}
}
true
}
}