1use std::{
5 borrow::Cow,
6 ffi::{OsStr, OsString},
7 fs, io,
8 path::{Path, PathBuf},
9};
10
11#[doc(alias = "realpath_ev")]
13pub fn canonicalize_path_ev<'a>(path: &'a Path) -> io::Result<PathBuf> {
14 let path = fs::canonicalize(path)?;
15 let path = normalize_path_ev(&path).into_owned();
16 Ok(path)
17}
18
19pub fn normalize_path_ev<'a>(path: &'a Path) -> Cow<'a, Path> {
27 let bytes = path.as_os_str().as_encoded_bytes();
28 if let Some(bytes) = bytes.strip_prefix(br"\\?\") {
29 if let Some(bytes) = bytes.strip_prefix(b"UNC") {
31 let s = unsafe { OsStr::from_encoded_bytes_unchecked(bytes) };
32 let mut buf = OsString::with_capacity(1 + s.len());
33 buf.push(OsStr::new("\\"));
34 buf.push(s);
35 return Cow::Owned(PathBuf::from(buf));
36 }
37
38 let s = unsafe { OsStr::from_encoded_bytes_unchecked(bytes) };
41 return Cow::Borrowed(Path::new(s));
42 }
43 Cow::Borrowed(path)
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn normalize_path_ev_verbatim_disk() {
52 let path = Path::new(r"\\?\C:\Windows");
54 let result = normalize_path_ev(path);
55 assert_eq!(result, Path::new(r"C:\Windows"));
56 }
57
58 #[test]
59 fn normalize_path_ev_regular_disk() {
60 let path = Path::new(r"C:\Windows");
62 let result = normalize_path_ev(path);
63 assert_eq!(result, Path::new(r"C:\Windows"));
64 }
65
66 #[test]
67 fn normalize_path_ev_verbatim_unc() {
68 let path = Path::new(r"\\?\UNC\server\share");
70 let result = normalize_path_ev(path);
71 assert_eq!(result, Path::new(r"\\server\share"));
72 }
73
74 #[test]
75 fn normalize_path_ev_relative() {
76 let path = Path::new("foo/bar");
78 let result = normalize_path_ev(path);
79 assert_eq!(result, Path::new("foo/bar"));
80 }
81
82 #[test]
83 fn normalize_path_ev_root_only() {
84 let path = Path::new(r"\\?\C:\");
86 let result = normalize_path_ev(path);
87 assert_eq!(result, Path::new(r"C:\"));
88 }
89}