use std::borrow::Cow;
#[must_use]
pub fn normalize_virtual_path(path: &str) -> Cow<'_, str> {
if is_normalized(path) {
Cow::Borrowed(path)
} else {
let mut out = String::with_capacity(path.len());
for segment in path.split('/') {
match segment {
"" | "." => {}
".." => out.truncate(out.rfind('/').unwrap_or(0)),
segment => {
out.push('/');
out.push_str(segment);
}
}
}
if out.is_empty() {
out.push('/');
}
Cow::Owned(out)
}
}
pub fn validate_cwd(cwd: &str) -> Result<String, String> {
if cwd.contains('\0') {
Err(format!("cwd must not contain NUL bytes: {cwd:?}"))
} else if !cwd.starts_with('/') {
Err(format!("cwd must be an absolute POSIX path: {cwd:?}"))
} else {
let trimmed = cwd.trim_end_matches('/');
Ok(if trimmed.is_empty() {
"/".to_owned()
} else {
trimmed.to_owned()
})
}
}
fn is_normalized(path: &str) -> bool {
path == "/"
|| (path.starts_with('/')
&& !path.ends_with('/')
&& path
.split('/')
.skip(1)
.all(|segment| !matches!(segment, "" | "." | "..")))
}