@@ -714,11 +714,21 @@ impl StrExt for str {
714714 }
715715
716716 #[ inline]
717- fn replacen_smolstr ( & self , from : & str , to : & str , count : usize ) -> SmolStr {
717+ fn replacen_smolstr ( & self , from : & str , to : & str , mut count : usize ) -> SmolStr {
718718 // Fast path for replacing a single ASCII character with another inline.
719719 if let [ from_u8] = from. as_bytes ( ) {
720720 if let [ to_u8] = to. as_bytes ( ) {
721- return replacen_1_ascii ( self , * from_u8, * to_u8, count) ;
721+ return match self . len ( ) <= count {
722+ true => replacen_1_ascii ( self , |b| if b == * from_u8 { * to_u8 } else { b } ) ,
723+ _ => replacen_1_ascii ( self , |b| {
724+ if b == * from_u8 && count != 0 {
725+ count -= 1 ;
726+ * to_u8
727+ } else {
728+ b
729+ }
730+ } ) ,
731+ } ;
722732 }
723733 }
724734
@@ -739,28 +749,19 @@ impl StrExt for str {
739749}
740750
741751#[ inline]
742- fn replacen_1_ascii ( src : & str , from : u8 , to : u8 , count : usize ) -> SmolStr {
743- let mut replaced = 0 ;
744- let mut ascii_replace = |b : & u8 | {
745- if * b == from && replaced != count {
746- replaced += 1 ;
747- to
748- } else {
749- * b
750- }
751- } ;
752+ fn replacen_1_ascii ( src : & str , mut map : impl FnMut ( u8 ) -> u8 ) -> SmolStr {
752753 if src. len ( ) <= INLINE_CAP {
753754 let mut buf = [ 0u8 ; INLINE_CAP ] ;
754755 for ( idx, b) in src. as_bytes ( ) . iter ( ) . enumerate ( ) {
755- buf[ idx] = ascii_replace ( b) ;
756+ buf[ idx] = map ( * b) ;
756757 }
757758 SmolStr ( Repr :: Inline {
758759 // SAFETY: `len` is in bounds
759760 len : unsafe { InlineSize :: transmute_from_u8 ( src. len ( ) as u8 ) } ,
760761 buf,
761762 } )
762763 } else {
763- let out = src. as_bytes ( ) . iter ( ) . map ( ascii_replace ) . collect ( ) ;
764+ let out = src. as_bytes ( ) . iter ( ) . map ( |b| map ( * b ) ) . collect ( ) ;
764765 // SAFETY: We replaced ascii with ascii on valid utf8 strings.
765766 unsafe { String :: from_utf8_unchecked ( out) . into ( ) }
766767 }
0 commit comments