Skip to content

Commit b1d6798

Browse files
committedJul 12, 2020
Rewrite parse_two_comps
1 parent 27a966a commit b1d6798

File tree

2 files changed

+41
-10
lines changed

2 files changed

+41
-10
lines changed
 

‎src/libstd/sys/windows/path.rs

+20-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ use crate::ffi::OsStr;
22
use crate::mem;
33
use crate::path::Prefix;
44

5+
#[cfg(test)]
6+
mod tests;
7+
58
pub const MAIN_SEP_STR: &str = "\\";
69
pub const MAIN_SEP: char = '\\';
710

@@ -43,7 +46,7 @@ pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
4346
if let Some(path) = path.strip_prefix(br"?\") {
4447
// \\?\UNC\server\share
4548
if let Some(path) = path.strip_prefix(br"UNC\") {
46-
let (server, share) = match parse_two_comps(path, is_verbatim_sep) {
49+
let (server, share) = match get_first_two_components(path, is_verbatim_sep) {
4750
Some((server, share)) => {
4851
(u8_slice_as_os_str(server), u8_slice_as_os_str(share))
4952
}
@@ -71,7 +74,7 @@ pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
7174
let slice = &path[..idx];
7275
return Some(DeviceNS(u8_slice_as_os_str(slice)));
7376
}
74-
match parse_two_comps(path, is_sep_byte) {
77+
match get_first_two_components(path, is_sep_byte) {
7578
Some((server, share)) if !server.is_empty() && !share.is_empty() => {
7679
// \\server\share
7780
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<'_>> {
8689
}
8790
return None;
8891
}
89-
90-
fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
91-
let first = &path[..path.iter().position(|x| f(*x))?];
92-
path = &path[(first.len() + 1)..];
93-
let idx = path.iter().position(|x| f(*x));
94-
let second = &path[..idx.unwrap_or(path.len())];
95-
Some((first, second))
96-
}
9792
}
9893

94+
/// Returns the first two path components with predicate `f`.
95+
///
96+
/// The two components returned will be use by caller
97+
/// to construct `VerbatimUNC` or `UNC` Windows path prefix.
98+
///
99+
/// Returns [`None`] if there are no separators in path.
100+
fn get_first_two_components(path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
101+
let idx = path.iter().position(|&x| f(x))?;
102+
// Panic safe
103+
// The max `idx+1` is `path.len()` and `path[path.len()..]` is a valid index.
104+
let (first, path) = (&path[..idx], &path[idx + 1..]);
105+
let idx = path.iter().position(|&x| f(x)).unwrap_or(path.len());
106+
let second = &path[..idx];
107+
Some((first, second))
108+
}

‎src/libstd/sys/windows/path/tests.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use super::*;
2+
3+
#[test]
4+
fn test_get_first_two_components() {
5+
assert_eq!(
6+
get_first_two_components(br"server\share", is_verbatim_sep),
7+
Some((&b"server"[..], &b"share"[..])),
8+
);
9+
10+
assert_eq!(
11+
get_first_two_components(br"server\", is_verbatim_sep),
12+
Some((&b"server"[..], &b""[..]))
13+
);
14+
15+
assert_eq!(
16+
get_first_two_components(br"\server\", is_verbatim_sep),
17+
Some((&b""[..], &b"server"[..]))
18+
);
19+
20+
assert_eq!(get_first_two_components(br"there are no separators here", is_verbatim_sep), None,);
21+
}

0 commit comments

Comments
 (0)