@@ -437,15 +437,31 @@ struct EscapeNonAsciiFormatter;
437437
438438impl Formatter for EscapeNonAsciiFormatter {
439439 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 ( ) ;
443453 } 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 ( ) ;
446457 }
447458 }
459+
460+ input = & input[ ( idx + non_ascii_char. len_utf8 ( ) ) ..] ;
448461 }
462+
463+ // write any ascii trailer
464+ writer. write_all ( fragment. as_bytes ( ) ) ?;
449465 Ok ( ( ) )
450466 }
451467}
@@ -484,7 +500,7 @@ macro_rules! defer {
484500}
485501
486502#[ allow( clippy:: needless_lifetimes) ]
487- impl < ' a > Formatter for EscapeNonAsciiPrettyFormatter < ' a > {
503+ impl Formatter for EscapeNonAsciiPrettyFormatter < ' _ > {
488504 defer ! ( escape_non_ascii, write_string_fragment, & str ) ;
489505 defer ! ( pretty, begin_array) ;
490506 defer ! ( pretty, end_array) ;
0 commit comments