@@ -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<u8> {
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 < u8 > = 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
+ }
0 commit comments