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)
|
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
|
/// The standard path separator character
|
||||||
pub static SEP: char = '\\';
|
pub static SEP: char = '\\';
|
||||||
/// The standard path separator byte
|
/// The standard path separator byte
|
||||||
@ -2284,4 +2316,38 @@ macro_rules! t(
|
|||||||
t!(s: ".", [b!(".")]);
|
t!(s: ".", [b!(".")]);
|
||||||
// since this is really a wrapper around str_components, those tests suffice
|
// 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