Skip to content

Commit

Permalink
Rewrite parse_two_comps
Browse files Browse the repository at this point in the history
  • Loading branch information
tesuji committed Jul 12, 2020
1 parent 27a966a commit b1d6798
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 10 deletions.
30 changes: 20 additions & 10 deletions src/libstd/sys/windows/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '\\';

Expand Down Expand Up @@ -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))
}
Expand Down Expand Up @@ -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)));
Expand All @@ -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))
}
21 changes: 21 additions & 0 deletions src/libstd/sys/windows/path/tests.rs
Original file line number Diff line number Diff line change
@@ -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,);
}

0 comments on commit b1d6798

Please sign in to comment.