@@ -2399,26 +2399,51 @@ impl Display for bool {
2399
2399
impl Debug for str {
2400
2400
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result {
2401
2401
f. write_char ( '"' ) ?;
2402
- let mut from = 0 ;
2403
- for ( i, c) in self . char_indices ( ) {
2404
- // a fast path for ASCII chars that do not need escapes:
2405
- if matches ! ( c, ' ' ..='~' ) && !matches ! ( c, '\\' | '\"' ) {
2406
- continue ;
2407
- }
2408
2402
2409
- let esc = c. escape_debug_ext ( EscapeDebugExtArgs {
2410
- escape_grapheme_extended : true ,
2411
- escape_single_quote : false ,
2412
- escape_double_quote : true ,
2413
- } ) ;
2414
- // If char needs escaping, flush backlog so far and write, else skip
2415
- if esc. len ( ) != 1 {
2416
- f. write_str ( & self [ from..i] ) ?;
2417
- Display :: fmt ( & esc, f) ?;
2418
- from = i + c. len_utf8 ( ) ;
2403
+ // substring we know is printable
2404
+ let mut printable_range = 0 ..0 ;
2405
+
2406
+ fn needs_escape ( b : u8 ) -> bool {
2407
+ b > 0x7E || b < 0x20 || b == b'\\' || b == b'"'
2408
+ }
2409
+
2410
+ // the outer loop here splits the string into chunks of printable ASCII, which is just skipped over,
2411
+ // and chunks of other chars (unicode, or ASCII that needs escaping), which is handler per-`char`.
2412
+ let mut rest = self . as_bytes ( ) ;
2413
+ while rest. len ( ) > 0 {
2414
+ let Some ( non_printable_start) = rest. iter ( ) . position ( |& b| needs_escape ( b) ) else {
2415
+ printable_range. end += rest. len ( ) ;
2416
+ break ;
2417
+ } ;
2418
+
2419
+ printable_range. end += non_printable_start;
2420
+ // SAFETY: the position was derived from an iterator, so is known to be within bounds, and at a char boundary
2421
+ rest = unsafe { rest. get_unchecked ( non_printable_start..) } ;
2422
+
2423
+ let printable_start = rest. iter ( ) . position ( |& b| !needs_escape ( b) ) . unwrap_or ( rest. len ( ) ) ;
2424
+ let prefix;
2425
+ // SAFETY: the position was derived from an iterator, so is known to be within bounds, and at a char boundary
2426
+ ( prefix, rest) = unsafe { rest. split_at_unchecked ( printable_start) } ;
2427
+ // SAFETY: prefix is a valid utf8 sequence, and at a char boundary
2428
+ let prefix = unsafe { crate :: str:: from_utf8_unchecked ( prefix) } ;
2429
+
2430
+ for c in prefix. chars ( ) {
2431
+ let esc = c. escape_debug_ext ( EscapeDebugExtArgs {
2432
+ escape_grapheme_extended : true ,
2433
+ escape_single_quote : false ,
2434
+ escape_double_quote : true ,
2435
+ } ) ;
2436
+ if esc. len ( ) != 1 {
2437
+ f. write_str ( & self [ printable_range. clone ( ) ] ) ?;
2438
+ Display :: fmt ( & esc, f) ?;
2439
+ printable_range. start = printable_range. end + c. len_utf8 ( ) ;
2440
+ }
2441
+ printable_range. end += c. len_utf8 ( ) ;
2419
2442
}
2420
2443
}
2421
- f. write_str ( & self [ from..] ) ?;
2444
+
2445
+ f. write_str ( & self [ printable_range] ) ?;
2446
+
2422
2447
f. write_char ( '"' )
2423
2448
}
2424
2449
}
0 commit comments