@@ -437,15 +437,31 @@ struct EscapeNonAsciiFormatter;
437
437
438
438
impl Formatter for EscapeNonAsciiFormatter {
439
439
fn write_string_fragment < W : ?Sized + Write > ( & mut self , writer : & mut W , fragment : & str ) -> io:: Result < ( ) > {
440
- for ch in fragment. chars ( ) {
441
- if ch. is_ascii ( ) {
442
- writer. write_all ( ch. encode_utf8 ( & mut [ 0 ; 4 ] ) . as_bytes ( ) ) ?;
440
+ let mut input = fragment;
441
+
442
+ while let Some ( ( idx, non_ascii_char) ) = input. chars ( ) . enumerate ( ) . find ( |( _, c) | !c. is_ascii ( ) ) {
443
+ if idx > 0 {
444
+ // write all ascii characters before the non-ascii one
445
+ let ascii_run = & input[ ..idx] ;
446
+ writer. write_all ( ascii_run. as_bytes ( ) ) . unwrap ( ) ;
447
+ }
448
+
449
+ let codepoint = non_ascii_char as u32 ;
450
+ if codepoint < 0xFFFF {
451
+ // write basic codepoint as single escape
452
+ write ! ( writer, "\\ u{codepoint:04x}" ) . unwrap ( ) ;
443
453
} else {
444
- for escape in ch. encode_utf16 ( & mut [ 0 ; 2 ] ) {
445
- write ! ( writer, "\\ u{escape:04x}" ) ?;
454
+ // encode extended plane character as utf16 pair
455
+ for escape in non_ascii_char. encode_utf16 ( & mut [ 0 ; 2 ] ) {
456
+ write ! ( writer, "\\ u{escape:04x}" ) . unwrap ( ) ;
446
457
}
447
458
}
459
+
460
+ input = & input[ ( idx + non_ascii_char. len_utf8 ( ) ) ..] ;
448
461
}
462
+
463
+ // write any ascii trailer
464
+ writer. write_all ( fragment. as_bytes ( ) ) ?;
449
465
Ok ( ( ) )
450
466
}
451
467
}
@@ -484,7 +500,7 @@ macro_rules! defer {
484
500
}
485
501
486
502
#[ allow( clippy:: needless_lifetimes) ]
487
- impl < ' a > Formatter for EscapeNonAsciiPrettyFormatter < ' a > {
503
+ impl Formatter for EscapeNonAsciiPrettyFormatter < ' _ > {
488
504
defer ! ( escape_non_ascii, write_string_fragment, & str ) ;
489
505
defer ! ( pretty, begin_array) ;
490
506
defer ! ( pretty, end_array) ;
0 commit comments