Skip to content

Commit 024c947

Browse files
committed
Add a fast path for OsStr prefix functions with str patterns.
1 parent 525fc99 commit 024c947

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

library/core/src/str/pattern.rs

+16
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ pub trait Pattern<'a>: Sized {
160160
None
161161
}
162162
}
163+
164+
/// Return the pattern as a fixed slice of UTF-8 bytes, if possible.
165+
#[inline]
166+
fn as_bytes(&self) -> Option<&[u8]> {
167+
None
168+
}
163169
}
164170

165171
// Searcher
@@ -917,6 +923,11 @@ where
917923
/// Delegates to the `&str` impl.
918924
impl<'a, 'b, 'c> Pattern<'a> for &'c &'b str {
919925
pattern_methods!(StrSearcher<'a, 'b>, |&s| s, |s| s);
926+
927+
#[inline]
928+
fn as_bytes(&self) -> Option<&[u8]> {
929+
(*self).as_bytes()
930+
}
920931
}
921932

922933
/////////////////////////////////////////////////////////////////////////////
@@ -1001,6 +1012,11 @@ impl<'a, 'b> Pattern<'a> for &'b str {
10011012
None
10021013
}
10031014
}
1015+
1016+
#[inline]
1017+
fn as_bytes(&self) -> Option<&[u8]> {
1018+
Some(str::as_bytes(self))
1019+
}
10041020
}
10051021

10061022
/////////////////////////////////////////////////////////////////////////////

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

+8
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,18 @@ impl Slice {
288288

289289
#[inline]
290290
pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pattern: P) -> bool {
291+
if let Some(pattern_bytes) = pattern.as_bytes() {
292+
return self.inner.starts_with(pattern_bytes);
293+
}
291294
self.to_str_prefix().starts_with(pattern)
292295
}
293296

294297
pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a Slice> {
298+
if let Some(prefix_bytes) = prefix.as_bytes() {
299+
let suffix = self.inner.strip_prefix(prefix_bytes)?;
300+
return Some(Slice::from_u8_slice(suffix));
301+
}
302+
295303
let p = self.to_str_prefix();
296304
let prefix_len = match prefix.into_searcher(p).next() {
297305
SearchStep::Match(0, prefix_len) => prefix_len,

library/std/src/sys_common/wtf8.rs

+10
Original file line numberDiff line numberDiff line change
@@ -801,10 +801,20 @@ impl Wtf8 {
801801

802802
#[inline]
803803
pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pattern: P) -> bool {
804+
if let Some(pattern_bytes) = pattern.as_bytes() {
805+
return self.bytes.starts_with(pattern_bytes);
806+
}
804807
self.to_str_prefix().starts_with(pattern)
805808
}
806809

807810
pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a Wtf8> {
811+
if let Some(prefix_bytes) = prefix.as_bytes() {
812+
let suffix = self.bytes.strip_prefix(prefix_bytes)?;
813+
// SAFETY: WTF-8 is a superset of UTF-8, so stripping off a UTF-8
814+
// prefix will yield a suffix that is valid WTF-8.
815+
return unsafe { Some(Wtf8::from_bytes_unchecked(suffix)) };
816+
}
817+
808818
let p = self.to_str_prefix();
809819
let prefix_len = match prefix.into_searcher(p).next() {
810820
SearchStep::Match(0, prefix_len) => prefix_len,

0 commit comments

Comments
 (0)