@@ -19,7 +19,7 @@ pub use core::str::SplitInclusive;
1919pub use core:: str:: SplitWhitespace ;
2020#[ stable( feature = "rust1" , since = "1.0.0" ) ]
2121pub use core:: str:: pattern;
22- use core:: str:: pattern:: { DoubleEndedSearcher , Pattern , ReverseSearcher , Searcher } ;
22+ use core:: str:: pattern:: { DoubleEndedSearcher , Pattern , ReverseSearcher , Searcher , Utf8Pattern } ;
2323#[ stable( feature = "rust1" , since = "1.0.0" ) ]
2424pub use core:: str:: { Bytes , CharIndices , Chars , from_utf8, from_utf8_mut} ;
2525#[ stable( feature = "str_escape" , since = "1.34.0" ) ]
@@ -268,6 +268,16 @@ impl str {
268268 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
269269 #[ inline]
270270 pub fn replace < P : Pattern > ( & self , from : P , to : & str ) -> String {
271+ // Fast path for ASCII to ASCII case.
272+ if let Some ( from_byte) = match from. as_utf8_pattern ( ) {
273+ Some ( Utf8Pattern :: Slice ( [ from_byte] ) ) => Some ( * from_byte) ,
274+ Some ( Utf8Pattern :: Char ( c) ) => c. as_ascii ( ) . map ( |ascii_char| ascii_char. to_u8 ( ) ) ,
275+ _ => None ,
276+ } {
277+ if let [ to_byte] = to. as_bytes ( ) {
278+ return unsafe { replace_ascii ( self . as_bytes ( ) , from_byte, * to_byte) } ;
279+ }
280+ }
271281 let mut result = String :: new ( ) ;
272282 let mut last_end = 0 ;
273283 for ( start, part) in self . match_indices ( from) {
@@ -661,3 +671,13 @@ fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> Vec<u8> {
661671
662672 out
663673}
674+ #[ inline]
675+ #[ cfg( not( test) ) ]
676+ #[ cfg( not( no_global_oom_handling) ) ]
677+ /// Faster implementation of string replacement for ASCII to ASCII cases.
678+ /// Should produce fast vectorized code.
679+ unsafe fn replace_ascii ( utf8_bytes : & [ u8 ] , from : u8 , to : u8 ) -> String {
680+ let result: Vec < u8 > = utf8_bytes. iter ( ) . map ( |b| if * b == from { to } else { * b } ) . collect ( ) ;
681+ // SAFETY: We replaced ascii with ascii on valid utf8 strings.
682+ unsafe { String :: from_utf8_unchecked ( result) }
683+ }
0 commit comments