use std::{
borrow::Cow,
ffi::{OsStr, OsString},
fs, io,
path::{Path, PathBuf},
};
#[doc(alias = "realpath_ev")]
pub fn canonicalize_path_ev<'a>(path: &'a Path) -> io::Result<PathBuf> {
let path = fs::canonicalize(path)?;
let path = normalize_path_ev(&path).into_owned();
Ok(path)
}
pub fn normalize_path_ev<'a>(path: &'a Path) -> Cow<'a, Path> {
let bytes = path.as_os_str().as_encoded_bytes();
if let Some(bytes) = bytes.strip_prefix(br"\\?\") {
if let Some(bytes) = bytes.strip_prefix(b"UNC") {
let s = unsafe { OsStr::from_encoded_bytes_unchecked(bytes) };
let mut buf = OsString::with_capacity(1 + s.len());
buf.push(OsStr::new("\\"));
buf.push(s);
return Cow::Owned(PathBuf::from(buf));
}
let s = unsafe { OsStr::from_encoded_bytes_unchecked(bytes) };
return Cow::Borrowed(Path::new(s));
}
Cow::Borrowed(path)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn normalize_path_ev_verbatim_disk() {
let path = Path::new(r"\\?\C:\Windows");
let result = normalize_path_ev(path);
assert_eq!(result, Path::new(r"C:\Windows"));
}
#[test]
fn normalize_path_ev_regular_disk() {
let path = Path::new(r"C:\Windows");
let result = normalize_path_ev(path);
assert_eq!(result, Path::new(r"C:\Windows"));
}
#[test]
fn normalize_path_ev_verbatim_unc() {
let path = Path::new(r"\\?\UNC\server\share");
let result = normalize_path_ev(path);
assert_eq!(result, Path::new(r"\\server\share"));
}
#[test]
fn normalize_path_ev_relative() {
let path = Path::new("foo/bar");
let result = normalize_path_ev(path);
assert_eq!(result, Path::new("foo/bar"));
}
#[test]
fn normalize_path_ev_root_only() {
let path = Path::new(r"\\?\C:\");
let result = normalize_path_ev(path);
assert_eq!(result, Path::new(r"C:\"));
}
}