@@ -1534,23 +1534,6 @@ pub enum CharEscape {
1534
1534
AsciiControl ( u8 ) ,
1535
1535
}
1536
1536
1537
- impl CharEscape {
1538
- #[ inline]
1539
- fn from_escape_table ( escape : u8 , byte : u8 ) -> CharEscape {
1540
- match escape {
1541
- self :: BB => CharEscape :: Backspace ,
1542
- self :: TT => CharEscape :: Tab ,
1543
- self :: NN => CharEscape :: LineFeed ,
1544
- self :: FF => CharEscape :: FormFeed ,
1545
- self :: RR => CharEscape :: CarriageReturn ,
1546
- self :: QU => CharEscape :: Quote ,
1547
- self :: BS => CharEscape :: ReverseSolidus ,
1548
- self :: UU => CharEscape :: AsciiControl ( byte) ,
1549
- _ => unreachable ! ( ) ,
1550
- }
1551
- }
1552
- }
1553
-
1554
1537
/// This trait abstracts away serializing the JSON control characters, which allows the user to
1555
1538
/// optionally pretty print the JSON output.
1556
1539
pub trait Formatter {
@@ -1784,30 +1767,33 @@ pub trait Formatter {
1784
1767
{
1785
1768
use self :: CharEscape :: * ;
1786
1769
1787
- let s = match char_escape {
1788
- Quote => b"\\ \" " ,
1789
- ReverseSolidus => b"\\ \\ " ,
1790
- Solidus => b"\\ /" ,
1791
- Backspace => b"\\ b" ,
1792
- FormFeed => b"\\ f" ,
1793
- LineFeed => b"\\ n" ,
1794
- CarriageReturn => b"\\ r" ,
1795
- Tab => b"\\ t" ,
1770
+ let escape_char = match char_escape {
1771
+ Quote => b'"' ,
1772
+ ReverseSolidus => b'\\' ,
1773
+ Solidus => b'/' ,
1774
+ Backspace => b'b' ,
1775
+ FormFeed => b'f' ,
1776
+ LineFeed => b'n' ,
1777
+ CarriageReturn => b'r' ,
1778
+ Tab => b't' ,
1779
+ AsciiControl ( _) => b'u' ,
1780
+ } ;
1781
+
1782
+ match char_escape {
1796
1783
AsciiControl ( byte) => {
1797
1784
static HEX_DIGITS : [ u8 ; 16 ] = * b"0123456789abcdef" ;
1798
1785
let bytes = & [
1799
1786
b'\\' ,
1800
- b'u' ,
1787
+ escape_char ,
1801
1788
b'0' ,
1802
1789
b'0' ,
1803
1790
HEX_DIGITS [ ( byte >> 4 ) as usize ] ,
1804
1791
HEX_DIGITS [ ( byte & 0xF ) as usize ] ,
1805
1792
] ;
1806
- return writer. write_all ( bytes) ;
1793
+ writer. write_all ( bytes)
1807
1794
}
1808
- } ;
1809
-
1810
- writer. write_all ( s)
1795
+ _ => writer. write_all ( & [ b'\\' , escape_char] ) ,
1796
+ }
1811
1797
}
1812
1798
1813
1799
/// Writes the representation of a byte array. Formatters can choose whether
@@ -2097,31 +2083,51 @@ where
2097
2083
W : ?Sized + io:: Write ,
2098
2084
F : ?Sized + Formatter ,
2099
2085
{
2100
- let bytes = value. as_bytes ( ) ;
2086
+ let mut bytes = value. as_bytes ( ) ;
2101
2087
2102
- let mut start = 0 ;
2088
+ let mut i = 0 ;
2089
+ while i < bytes. len ( ) {
2090
+ let ( string_run, rest) = bytes. split_at ( i) ;
2091
+ let ( & byte, rest) = rest. split_first ( ) . unwrap ( ) ;
2103
2092
2104
- for ( i, & byte) in bytes. iter ( ) . enumerate ( ) {
2105
2093
let escape = ESCAPE [ byte as usize ] ;
2094
+
2095
+ i += 1 ;
2106
2096
if escape == 0 {
2107
2097
continue ;
2108
2098
}
2109
2099
2110
- if start < i {
2111
- tri ! ( formatter. write_string_fragment( writer, & value[ start..i] ) ) ;
2100
+ bytes = rest;
2101
+ i = 0 ;
2102
+
2103
+ // safety: string_run is a valid utf8 string, since we only split on ascii sequences
2104
+ let string_run = unsafe { core:: str:: from_utf8_unchecked ( string_run) } ;
2105
+ if !string_run. is_empty ( ) {
2106
+ tri ! ( formatter. write_string_fragment( writer, string_run) ) ;
2112
2107
}
2113
2108
2114
- let char_escape = CharEscape :: from_escape_table ( escape, byte) ;
2109
+ let char_escape = match escape {
2110
+ self :: BB => CharEscape :: Backspace ,
2111
+ self :: TT => CharEscape :: Tab ,
2112
+ self :: NN => CharEscape :: LineFeed ,
2113
+ self :: FF => CharEscape :: FormFeed ,
2114
+ self :: RR => CharEscape :: CarriageReturn ,
2115
+ self :: QU => CharEscape :: Quote ,
2116
+ self :: BS => CharEscape :: ReverseSolidus ,
2117
+ self :: UU => CharEscape :: AsciiControl ( byte) ,
2118
+ // safety: the escape table does not contain any other type of character.
2119
+ _ => unsafe { core:: hint:: unreachable_unchecked ( ) } ,
2120
+ } ;
2115
2121
tri ! ( formatter. write_char_escape( writer, char_escape) ) ;
2116
-
2117
- start = i + 1 ;
2118
2122
}
2119
2123
2120
- if start == bytes. len ( ) {
2124
+ // safety: bytes is a valid utf8 string, since we only split on ascii sequences
2125
+ let string_run = unsafe { core:: str:: from_utf8_unchecked ( bytes) } ;
2126
+ if string_run. is_empty ( ) {
2121
2127
return Ok ( ( ) ) ;
2122
2128
}
2123
2129
2124
- formatter. write_string_fragment ( writer, & value [ start.. ] )
2130
+ formatter. write_string_fragment ( writer, string_run )
2125
2131
}
2126
2132
2127
2133
const BB : u8 = b'b' ; // \x08
0 commit comments