path: Implement windows::make_non_verbatim()
make_non_verbatim() takes a WindowsPath and returns a new one that does not use the \\?\ verbatim prefix, if possible.
This commit is contained in:
parent
af38726d8e
commit
ea0bd40d9b
@ -871,6 +871,38 @@ pub fn is_verbatim(path: &Path) -> bool {
|
||||
prefix_is_verbatim(path.prefix)
|
||||
}
|
||||
|
||||
/// Returns the non-verbatim equivalent of the input path, if possible.
|
||||
/// If the input path is a device namespace path, None is returned.
|
||||
/// If the input path is not verbatim, it is returned as-is.
|
||||
/// If the input path is verbatim, but the same path can be expressed as
|
||||
/// non-verbatim, the non-verbatim version is returned.
|
||||
/// Otherwise, None is returned.
|
||||
pub fn make_non_verbatim(path: &Path) -> Option<Path> {
|
||||
let new_path = match path.prefix {
|
||||
Some(VerbatimPrefix(_)) | Some(DeviceNSPrefix(_)) => return None,
|
||||
Some(UNCPrefix(_,_)) | Some(DiskPrefix) | None => return Some(path.clone()),
|
||||
Some(VerbatimDiskPrefix) => {
|
||||
// \\?\D:\
|
||||
Path::new(path.repr.slice_from(4))
|
||||
}
|
||||
Some(VerbatimUNCPrefix(_,_)) => {
|
||||
// \\?\UNC\server\share
|
||||
Path::new(format!(r"\\{}", path.repr.slice_from(7)))
|
||||
}
|
||||
};
|
||||
if new_path.prefix.is_none() {
|
||||
// \\?\UNC\server is a VerbatimUNCPrefix
|
||||
// but \\server is nothing
|
||||
return None;
|
||||
}
|
||||
// now ensure normalization didn't change anything
|
||||
if path.repr.slice_from(path.prefix_len()) == new_path.repr.slice_from(new_path.prefix_len()) {
|
||||
Some(new_path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// The standard path separator character
|
||||
pub static SEP: char = '\\';
|
||||
/// The standard path separator byte
|
||||
@ -2284,4 +2316,38 @@ macro_rules! t(
|
||||
t!(s: ".", [b!(".")]);
|
||||
// since this is really a wrapper around str_components, those tests suffice
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_make_non_verbatim() {
|
||||
macro_rules! t(
|
||||
($path:expr, $exp:expr) => (
|
||||
{
|
||||
let path = Path::new($path);
|
||||
let exp: Option<&str> = $exp;
|
||||
let exp = exp.map(|s| Path::new(s));
|
||||
assert_eq!(make_non_verbatim(&path), exp);
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
t!(r"\a\b\c", Some(r"\a\b\c"));
|
||||
t!(r"a\b\c", Some(r"a\b\c"));
|
||||
t!(r"C:\a\b\c", Some(r"C:\a\b\c"));
|
||||
t!(r"C:a\b\c", Some(r"C:a\b\c"));
|
||||
t!(r"\\server\share\foo", Some(r"\\server\share\foo"));
|
||||
t!(r"\\.\foo", None);
|
||||
t!(r"\\?\foo", None);
|
||||
t!(r"\\?\C:", None);
|
||||
t!(r"\\?\C:foo", None);
|
||||
t!(r"\\?\C:\", Some(r"C:\"));
|
||||
t!(r"\\?\C:\foo", Some(r"C:\foo"));
|
||||
t!(r"\\?\C:\foo\bar\baz", Some(r"C:\foo\bar\baz"));
|
||||
t!(r"\\?\C:\foo\.\bar\baz", None);
|
||||
t!(r"\\?\C:\foo\bar\..\baz", None);
|
||||
t!(r"\\?\C:\foo\bar\..", None);
|
||||
t!(r"\\?\UNC\server\share\foo", Some(r"\\server\share\foo"));
|
||||
t!(r"\\?\UNC\server\share", Some(r"\\server\share"));
|
||||
t!(r"\\?\UNC\server", None);
|
||||
t!(r"\\?\UNC\server\", None);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user