Auto merge of #130223 - LaihoE:faster_str_replace, r=thomcc · qinheping/verify-rust-std@0d7c889 (original) (raw)

`@@ -20,7 +20,7 @@ pub use core::str::SplitInclusive;

`

20

20

`pub use core::str::SplitWhitespace;

`

21

21

`#[stable(feature = "rust1", since = "1.0.0")]

`

22

22

`pub use core::str::pattern;

`

23

``

`-

use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher};

`

``

23

`+

use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher, Utf8Pattern};

`

24

24

`#[stable(feature = "rust1", since = "1.0.0")]

`

25

25

`pub use core::str::{Bytes, CharIndices, Chars, from_utf8, from_utf8_mut};

`

26

26

`#[stable(feature = "str_escape", since = "1.34.0")]

`

`@@ -269,6 +269,18 @@ impl str {

`

269

269

`#[stable(feature = "rust1", since = "1.0.0")]

`

270

270

`#[inline]

`

271

271

`pub fn replace<P: Pattern>(&self, from: P, to: &str) -> String {

`

``

272

`+

// Fast path for ASCII to ASCII case.

`

``

273

+

``

274

`+

if let Some(from_byte) = match from.as_utf8_pattern() {

`

``

275

`+

Some(Utf8Pattern::StringPattern([from_byte])) => Some(*from_byte),

`

``

276

`+

Some(Utf8Pattern::CharPattern(c)) => c.as_ascii().map(|ascii_char| ascii_char.to_u8()),

`

``

277

`+

_ => None,

`

``

278

`+

} {

`

``

279

`+

if let [to_byte] = to.as_bytes() {

`

``

280

`+

return unsafe { replace_ascii(self.as_bytes(), from_byte, *to_byte) };

`

``

281

`+

}

`

``

282

`+

}

`

``

283

+

272

284

`let mut result = String::new();

`

273

285

`let mut last_end = 0;

`

274

286

`for (start, part) in self.match_indices(from) {

`

`@@ -686,3 +698,14 @@ pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) {

`

686

698

`(ascii_string, rest)

`

687

699

`}

`

688

700

`}

`

``

701

`+

#[inline]

`

``

702

`+

#[cfg(not(test))]

`

``

703

`+

#[cfg(not(no_global_oom_handling))]

`

``

704

`+

#[allow(dead_code)]

`

``

705

`+

/// Faster implementation of string replacement for ASCII to ASCII cases.

`

``

706

`+

/// Should produce fast vectorized code.

`

``

707

`+

unsafe fn replace_ascii(utf8_bytes: &[u8], from: u8, to: u8) -> String {

`

``

708

`+

let result: Vec = utf8_bytes.iter().map(|b| if *b == from { to } else { *b }).collect();

`

``

709

`+

// SAFETY: We replaced ascii with ascii on valid utf8 strings.

`

``

710

`+

unsafe { String::from_utf8_unchecked(result) }

`

``

711

`+

}

`