Skip to content

Commit 2ee6afb

Browse files
committed
skip some Path prefix-component logic on platforms that don't have prefixes
1 parent dccbf42 commit 2ee6afb

File tree

7 files changed

+44
-24
lines changed

7 files changed

+44
-24
lines changed

library/std/src/path.rs

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ use crate::ops::{self, Deref};
7979
use crate::rc::Rc;
8080
use crate::str::FromStr;
8181
use crate::sync::Arc;
82-
use crate::sys::path::{MAIN_SEP_STR, is_sep_byte, is_verbatim_sep, parse_prefix};
82+
use crate::sys::path::{HAS_PREFIXES, MAIN_SEP_STR, is_sep_byte, is_verbatim_sep, parse_prefix};
8383
use crate::{cmp, fmt, fs, io, sys};
8484

8585
////////////////////////////////////////////////////////////////////////////////
@@ -643,17 +643,26 @@ impl<'a> Components<'a> {
643643
// how long is the prefix, if any?
644644
#[inline]
645645
fn prefix_len(&self) -> usize {
646+
if !HAS_PREFIXES {
647+
return 0;
648+
}
646649
self.prefix.as_ref().map(Prefix::len).unwrap_or(0)
647650
}
648651

649652
#[inline]
650653
fn prefix_verbatim(&self) -> bool {
654+
if !HAS_PREFIXES {
655+
return false;
656+
}
651657
self.prefix.as_ref().map(Prefix::is_verbatim).unwrap_or(false)
652658
}
653659

654660
/// how much of the prefix is left from the point of view of iteration?
655661
#[inline]
656662
fn prefix_remaining(&self) -> usize {
663+
if !HAS_PREFIXES {
664+
return 0;
665+
}
657666
if self.front == State::Prefix { self.prefix_len() } else { 0 }
658667
}
659668

@@ -707,7 +716,7 @@ impl<'a> Components<'a> {
707716
if self.has_physical_root {
708717
return true;
709718
}
710-
if let Some(p) = self.prefix {
719+
if HAS_PREFIXES && let Some(p) = self.prefix {
711720
if p.has_implicit_root() {
712721
return true;
713722
}
@@ -732,7 +741,7 @@ impl<'a> Components<'a> {
732741
// corresponding path component
733742
unsafe fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
734743
match comp {
735-
b"." if self.prefix_verbatim() => Some(Component::CurDir),
744+
b"." if HAS_PREFIXES && self.prefix_verbatim() => Some(Component::CurDir),
736745
b"." => None, // . components are normalized away, except at
737746
// the beginning of a path, which is treated
738747
// separately via `include_cur_dir`
@@ -889,26 +898,24 @@ impl<'a> Iterator for Components<'a> {
889898
fn next(&mut self) -> Option<Component<'a>> {
890899
while !self.finished() {
891900
match self.front {
892-
State::Prefix if self.prefix_len() > 0 => {
893-
self.front = State::StartDir;
894-
debug_assert!(self.prefix_len() <= self.path.len());
895-
let raw = &self.path[..self.prefix_len()];
896-
self.path = &self.path[self.prefix_len()..];
897-
return Some(Component::Prefix(PrefixComponent {
898-
raw: unsafe { OsStr::from_encoded_bytes_unchecked(raw) },
899-
parsed: self.prefix.unwrap(),
900-
}));
901+
// most likely case first
902+
State::Body if !self.path.is_empty() => {
903+
let (size, comp) = self.parse_next_component();
904+
self.path = &self.path[size..];
905+
if comp.is_some() {
906+
return comp;
907+
}
901908
}
902-
State::Prefix => {
903-
self.front = State::StartDir;
909+
State::Body => {
910+
self.front = State::Done;
904911
}
905912
State::StartDir => {
906913
self.front = State::Body;
907914
if self.has_physical_root {
908915
debug_assert!(!self.path.is_empty());
909916
self.path = &self.path[1..];
910917
return Some(Component::RootDir);
911-
} else if let Some(p) = self.prefix {
918+
} else if HAS_PREFIXES && let Some(p) = self.prefix {
912919
if p.has_implicit_root() && !p.is_verbatim() {
913920
return Some(Component::RootDir);
914921
}
@@ -918,15 +925,19 @@ impl<'a> Iterator for Components<'a> {
918925
return Some(Component::CurDir);
919926
}
920927
}
921-
State::Body if !self.path.is_empty() => {
922-
let (size, comp) = self.parse_next_component();
923-
self.path = &self.path[size..];
924-
if comp.is_some() {
925-
return comp;
926-
}
928+
_ if const { !HAS_PREFIXES } => unreachable!(),
929+
State::Prefix if self.prefix_len() == 0 => {
930+
self.front = State::StartDir;
927931
}
928-
State::Body => {
929-
self.front = State::Done;
932+
State::Prefix => {
933+
self.front = State::StartDir;
934+
debug_assert!(self.prefix_len() <= self.path.len());
935+
let raw = &self.path[..self.prefix_len()];
936+
self.path = &self.path[self.prefix_len()..];
937+
return Some(Component::Prefix(PrefixComponent {
938+
raw: unsafe { OsStr::from_encoded_bytes_unchecked(raw) },
939+
parsed: self.prefix.unwrap(),
940+
}));
930941
}
931942
State::Done => unreachable!(),
932943
}
@@ -964,6 +975,7 @@ impl<'a> DoubleEndedIterator for Components<'a> {
964975
return Some(Component::CurDir);
965976
}
966977
}
978+
_ if !HAS_PREFIXES => unreachable!(),
967979
State::Prefix if self.prefix_len() > 0 => {
968980
self.back = State::Done;
969981
return Some(Component::Prefix(PrefixComponent {
@@ -3116,7 +3128,9 @@ impl Path {
31163128
path: self.as_u8_slice(),
31173129
prefix,
31183130
has_physical_root: has_physical_root(self.as_u8_slice(), prefix),
3119-
front: State::Prefix,
3131+
// use a platform-specific initial state to avoid one turn of
3132+
// the state-machine when the platform doesn't have a Prefix.
3133+
front: const { if HAS_PREFIXES { State::Prefix } else { State::StartDir } },
31203134
back: State::Body,
31213135
}
31223136
}

library/std/src/sys/path/cygwin.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub fn is_verbatim_sep(b: u8) -> bool {
2121

2222
pub use super::windows_prefix::parse_prefix;
2323

24+
pub const HAS_PREFIXES: bool = true;
2425
pub const MAIN_SEP_STR: &str = "/";
2526
pub const MAIN_SEP: char = '/';
2627

library/std/src/sys/path/sgx.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
1717
None
1818
}
1919

20+
pub const HAS_PREFIXES: bool = false;
2021
pub const MAIN_SEP_STR: &str = "/";
2122
pub const MAIN_SEP: char = '/';
2223

library/std/src/sys/path/uefi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
2121
None
2222
}
2323

24+
pub const HAS_PREFIXES: bool = true;
2425
pub const MAIN_SEP_STR: &str = "\\";
2526
pub const MAIN_SEP: char = '\\';
2627

library/std/src/sys/path/unix.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
1717
None
1818
}
1919

20+
pub const HAS_PREFIXES: bool = false;
2021
pub const MAIN_SEP_STR: &str = "/";
2122
pub const MAIN_SEP: char = '/';
2223

library/std/src/sys/path/unsupported_backslash.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
1818
None
1919
}
2020

21+
pub const HAS_PREFIXES: bool = true;
2122
pub const MAIN_SEP_STR: &str = "\\";
2223
pub const MAIN_SEP: char = '\\';
2324

library/std/src/sys/path/windows.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod tests;
99

1010
pub use super::windows_prefix::parse_prefix;
1111

12+
pub const HAS_PREFIXES: bool = true;
1213
pub const MAIN_SEP_STR: &str = "\\";
1314
pub const MAIN_SEP: char = '\\';
1415

0 commit comments

Comments
 (0)