about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLzu Tao <taolzu@gmail.com>2020-07-10 15:59:25 +0000
committerLzu Tao <taolzu@gmail.com>2020-07-12 14:51:04 +0000
commitb1d6798899b7830e869d06e1ddb106a75cb61cc8 (patch)
treeca543ff0b475327a1054967550632729fbada618
parent27a966a149f55fe29a25a2fc07e6c8a011ae3dbf (diff)
downloadrust-b1d6798899b7830e869d06e1ddb106a75cb61cc8.tar.gz
rust-b1d6798899b7830e869d06e1ddb106a75cb61cc8.zip
Rewrite parse_two_comps
-rw-r--r--src/libstd/sys/windows/path.rs30
-rw-r--r--src/libstd/sys/windows/path/tests.rs21
2 files changed, 41 insertions, 10 deletions
diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs
index 25ecc79abf0..fa22d3bb7d6 100644
--- a/src/libstd/sys/windows/path.rs
+++ b/src/libstd/sys/windows/path.rs
@@ -2,6 +2,9 @@ use crate::ffi::OsStr;
 use crate::mem;
 use crate::path::Prefix;
 
+#[cfg(test)]
+mod tests;
+
 pub const MAIN_SEP_STR: &str = "\\";
 pub const MAIN_SEP: char = '\\';
 
@@ -43,7 +46,7 @@ pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
             if let Some(path) = path.strip_prefix(br"?\") {
                 // \\?\UNC\server\share
                 if let Some(path) = path.strip_prefix(br"UNC\") {
-                    let (server, share) = match parse_two_comps(path, is_verbatim_sep) {
+                    let (server, share) = match get_first_two_components(path, is_verbatim_sep) {
                         Some((server, share)) => {
                             (u8_slice_as_os_str(server), u8_slice_as_os_str(share))
                         }
@@ -71,7 +74,7 @@ pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
                 let slice = &path[..idx];
                 return Some(DeviceNS(u8_slice_as_os_str(slice)));
             }
-            match parse_two_comps(path, is_sep_byte) {
+            match get_first_two_components(path, is_sep_byte) {
                 Some((server, share)) if !server.is_empty() && !share.is_empty() => {
                     // \\server\share
                     return Some(UNC(u8_slice_as_os_str(server), u8_slice_as_os_str(share)));
@@ -86,13 +89,20 @@ pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
         }
         return None;
     }
-
-    fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
-        let first = &path[..path.iter().position(|x| f(*x))?];
-        path = &path[(first.len() + 1)..];
-        let idx = path.iter().position(|x| f(*x));
-        let second = &path[..idx.unwrap_or(path.len())];
-        Some((first, second))
-    }
 }
 
+/// Returns the first two path components with predicate `f`.
+///
+/// The two components returned will be use by caller
+/// to construct `VerbatimUNC` or `UNC` Windows path prefix.
+///
+/// Returns [`None`] if there are no separators in path.
+fn get_first_two_components(path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
+    let idx = path.iter().position(|&x| f(x))?;
+    // Panic safe
+    // The max `idx+1` is `path.len()` and `path[path.len()..]` is a valid index.
+    let (first, path) = (&path[..idx], &path[idx + 1..]);
+    let idx = path.iter().position(|&x| f(x)).unwrap_or(path.len());
+    let second = &path[..idx];
+    Some((first, second))
+}
diff --git a/src/libstd/sys/windows/path/tests.rs b/src/libstd/sys/windows/path/tests.rs
new file mode 100644
index 00000000000..fbac1dc1ca1
--- /dev/null
+++ b/src/libstd/sys/windows/path/tests.rs
@@ -0,0 +1,21 @@
+use super::*;
+
+#[test]
+fn test_get_first_two_components() {
+    assert_eq!(
+        get_first_two_components(br"server\share", is_verbatim_sep),
+        Some((&b"server"[..], &b"share"[..])),
+    );
+
+    assert_eq!(
+        get_first_two_components(br"server\", is_verbatim_sep),
+        Some((&b"server"[..], &b""[..]))
+    );
+
+    assert_eq!(
+        get_first_two_components(br"\server\", is_verbatim_sep),
+        Some((&b""[..], &b"server"[..]))
+    );
+
+    assert_eq!(get_first_two_components(br"there are no separators here", is_verbatim_sep), None,);
+}