@@ -75,7 +75,7 @@ impl<'a> ToCss for Token<'a> {
75
75
serialize_unquoted_url ( & * * value, dest) ?;
76
76
dest. write_str ( ")" ) ?;
77
77
} ,
78
- Token :: Delim ( value) => write ! ( dest, "{}" , value) ?,
78
+ Token :: Delim ( value) => dest. write_char ( value) ?,
79
79
80
80
Token :: Number { value, int_value, has_sign } => {
81
81
write_numeric ( value, int_value, has_sign, dest) ?
@@ -97,7 +97,11 @@ impl<'a> ToCss for Token<'a> {
97
97
} ,
98
98
99
99
Token :: WhiteSpace ( content) => dest. write_str ( content) ?,
100
- Token :: Comment ( content) => write ! ( dest, "/*{}*/" , content) ?,
100
+ Token :: Comment ( content) => {
101
+ dest. write_str ( "/*" ) ?;
102
+ dest. write_str ( content) ?;
103
+ dest. write_str ( "*/" ) ?
104
+ }
101
105
Token :: Colon => dest. write_str ( ":" ) ?,
102
106
Token :: Semicolon => dest. write_str ( ";" ) ?,
103
107
Token :: Comma => dest. write_str ( "," ) ?,
@@ -128,6 +132,32 @@ impl<'a> ToCss for Token<'a> {
128
132
}
129
133
}
130
134
135
+ fn to_hex_byte ( value : u8 ) -> u8 {
136
+ match value {
137
+ 0 ...9 => value + b'0' ,
138
+ _ => value - 10 + b'a' ,
139
+ }
140
+ }
141
+
142
+ fn hex_escape < W > ( ascii_byte : u8 , dest : & mut W ) -> fmt:: Result where W : fmt:: Write {
143
+ let high = ascii_byte >> 4 ;
144
+ let b3;
145
+ let b4;
146
+ let bytes = if high > 0 {
147
+ let low = ascii_byte & 0x0F ;
148
+ b4 = [ b'\\' , to_hex_byte ( high) , to_hex_byte ( low) , b' ' ] ;
149
+ & b4[ ..]
150
+ } else {
151
+ b3 = [ b'\\' , to_hex_byte ( ascii_byte) , b' ' ] ;
152
+ & b3[ ..]
153
+ } ;
154
+ dest. write_str ( unsafe { str:: from_utf8_unchecked ( & bytes) } )
155
+ }
156
+
157
+ fn char_escape < W > ( ascii_byte : u8 , dest : & mut W ) -> fmt:: Result where W : fmt:: Write {
158
+ let bytes = [ b'\\' , ascii_byte] ;
159
+ dest. write_str ( unsafe { str:: from_utf8_unchecked ( & bytes) } )
160
+ }
131
161
132
162
/// Write a CSS identifier, escaping characters as necessary.
133
163
pub fn serialize_identifier < W > ( mut value : & str , dest : & mut W ) -> fmt:: Result where W : fmt:: Write {
@@ -146,7 +176,7 @@ pub fn serialize_identifier<W>(mut value: &str, dest: &mut W) -> fmt::Result whe
146
176
value = & value[ 1 ..] ;
147
177
}
148
178
if let digit @ b'0' ...b'9' = value. as_bytes ( ) [ 0 ] {
149
- write ! ( dest , " \\ 3{} " , digit as char ) ?;
179
+ hex_escape ( digit , dest ) ?;
150
180
value = & value[ 1 ..] ;
151
181
}
152
182
serialize_name ( value, dest)
@@ -167,9 +197,9 @@ fn serialize_name<W>(value: &str, dest: &mut W) -> fmt::Result where W:fmt::Writ
167
197
if let Some ( escaped) = escaped {
168
198
dest. write_str ( escaped) ?;
169
199
} else if ( b >= b'\x01' && b <= b'\x1F' ) || b == b'\x7F' {
170
- write ! ( dest , " \\ {:x} " , b ) ?;
200
+ hex_escape ( b , dest ) ?;
171
201
} else {
172
- write ! ( dest , " \\ {}" , b as char ) ?;
202
+ char_escape ( b , dest ) ?;
173
203
}
174
204
chunk_start = i + 1 ;
175
205
}
@@ -187,9 +217,9 @@ fn serialize_unquoted_url<W>(value: &str, dest: &mut W) -> fmt::Result where W:f
187
217
} ;
188
218
dest. write_str ( & value[ chunk_start..i] ) ?;
189
219
if hex {
190
- write ! ( dest , " \\ {:X} " , b ) ?;
220
+ hex_escape ( b , dest ) ?;
191
221
} else {
192
- write ! ( dest , " \\ {}" , b as char ) ?;
222
+ char_escape ( b , dest ) ?;
193
223
}
194
224
chunk_start = i + 1 ;
195
225
}
@@ -247,7 +277,7 @@ impl<'a, W> fmt::Write for CssStringWriter<'a, W> where W: fmt::Write {
247
277
self . inner . write_str ( & s[ chunk_start..i] ) ?;
248
278
match escaped {
249
279
Some ( x) => self . inner . write_str ( x) ?,
250
- None => write ! ( self . inner, " \\ {:x} " , b ) ?,
280
+ None => hex_escape ( b , self . inner ) ?,
251
281
} ;
252
282
chunk_start = i + 1 ;
253
283
}
@@ -265,7 +295,8 @@ macro_rules! impl_tocss_for_int {
265
295
impl <W : fmt:: Write > io:: Write for AssumeUtf8 <W > {
266
296
#[ inline]
267
297
fn write_all( & mut self , buf: & [ u8 ] ) -> io:: Result <( ) > {
268
- // Safety: itoa only emits ASCII
298
+ // Safety: itoa only emits ASCII, which is also well-formed UTF-8.
299
+ debug_assert!( buf. is_ascii( ) ) ;
269
300
self . 0 . write_str( unsafe { str :: from_utf8_unchecked( buf) } )
270
301
. map_err( |_| io:: ErrorKind :: Other . into( ) )
271
302
}
0 commit comments