use std::path::PathBuf;
mod metadata;
pub use metadata::{SymlinkMetadata, symlink_metadata};
use crate::ResolveError;
pub fn strip_windows_prefix(path: PathBuf) -> Result<PathBuf, ResolveError> {
let path_bytes = path.as_os_str().as_encoded_bytes();
let path = if let Some(p) =
path_bytes.strip_prefix(br"\\?\UNC\").or_else(|| path_bytes.strip_prefix(br"\\.\UNC\"))
{
unsafe {
PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(&[br"\\", p].concat()))
}
} else if let Some(p) =
path_bytes.strip_prefix(br"\\?\").or_else(|| path_bytes.strip_prefix(br"\\.\"))
{
if p[1] != b':' {
#[cold]
fn unsupported_path_error(path: PathBuf) -> ResolveError {
ResolveError::PathNotSupported(path)
}
return Err(unsupported_path_error(path));
}
unsafe { PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(p)) }
} else {
path
};
Ok(path)
}
#[test]
fn test_strip_windows_prefix() {
let pass = [
(r"C:\Users\user\Documents\", r"C:\Users\user\Documents\"),
(r"C:\Users\user\Documents\file1.txt", r"C:\Users\user\Documents\file1.txt"),
(r"\\?\C:\Users\user\Documents\", r"C:\Users\user\Documents\"),
(r"\\?\C:\Users\user\Documents\file1.txt", r"C:\Users\user\Documents\file1.txt"),
(r"\\.\C:\Users\user\Documents\file2.txt", r"C:\Users\user\Documents\file2.txt"),
(r"\\?\UNC\server\share\file3.txt", r"\\server\share\file3.txt"),
];
for (path, expected) in pass {
assert_eq!(strip_windows_prefix(PathBuf::from(path)), Ok(PathBuf::from(expected)));
}
let fail = [
r"\\?\Volume{c8ec34d8-3ba6-45c3-9b9d-3e4148e12d00}\file4.txt",
r"\\?\BootPartition\file4.txt",
];
for path in fail {
assert_eq!(
strip_windows_prefix(PathBuf::from(path)),
Err(crate::ResolveError::PathNotSupported(PathBuf::from(path)))
);
}
}