Add fast path for ascii to ascii in str::replace · qinheping/verify-rust-std@27136c4 (original) (raw)

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

`

19

19

`pub use core::str::SplitWhitespace;

`

20

20

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

`

21

21

`pub use core::str::pattern;

`

22

``

`-

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

`

``

22

`+

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

`

23

23

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

`

24

24

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

`

25

25

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

`

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

`

268

268

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

`

269

269

`#[inline]

`

270

270

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

`

``

271

`+

// Fast path for ASCII to ASCII case.

`

``

272

+

``

273

`+

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

`

``

274

`+

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

`

``

275

`+

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

`

``

276

`+

_ => None,

`

``

277

`+

} {

`

``

278

`+

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

`

``

279

`+

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

`

``

280

`+

}

`

``

281

`+

}

`

``

282

+

271

283

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

`

272

284

`let mut last_end = 0;

`

273

285

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

`

`@@ -661,3 +673,14 @@ fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> Vec {

`

661

673

``

662

674

` out

`

663

675

`}

`

``

676

`+

#[inline]

`

``

677

`+

#[cfg(not(test))]

`

``

678

`+

#[cfg(not(no_global_oom_handling))]

`

``

679

`+

#[allow(dead_code)]

`

``

680

`+

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

`

``

681

`+

/// Should produce fast vectorized code.

`

``

682

`+

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

`

``

683

`+

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

`

``

684

`+

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

`

``

685

`+

unsafe { String::from_utf8_unchecked(result) }

`

``

686

`+

}

`