@@ -75,7 +75,7 @@ impl<'a> ToCss for Token<'a> {
7575 serialize_unquoted_url ( & * * value, dest) ?;
7676 dest. write_str ( ")" ) ?;
7777 } ,
78- Token :: Delim ( value) => write ! ( dest, "{}" , value) ?,
78+ Token :: Delim ( value) => dest. write_char ( value) ?,
7979
8080 Token :: Number { value, int_value, has_sign } => {
8181 write_numeric ( value, int_value, has_sign, dest) ?
@@ -97,7 +97,11 @@ impl<'a> ToCss for Token<'a> {
9797 } ,
9898
9999 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+ }
101105 Token :: Colon => dest. write_str ( ":" ) ?,
102106 Token :: Semicolon => dest. write_str ( ";" ) ?,
103107 Token :: Comma => dest. write_str ( "," ) ?,
@@ -128,6 +132,32 @@ impl<'a> ToCss for Token<'a> {
128132 }
129133}
130134
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+ }
131161
132162/// Write a CSS identifier, escaping characters as necessary.
133163pub 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
146176 value = & value[ 1 ..] ;
147177 }
148178 if let digit @ b'0' ...b'9' = value. as_bytes ( ) [ 0 ] {
149- write ! ( dest , " \\ 3{} " , digit as char ) ?;
179+ hex_escape ( digit , dest ) ?;
150180 value = & value[ 1 ..] ;
151181 }
152182 serialize_name ( value, dest)
@@ -167,9 +197,9 @@ fn serialize_name<W>(value: &str, dest: &mut W) -> fmt::Result where W:fmt::Writ
167197 if let Some ( escaped) = escaped {
168198 dest. write_str ( escaped) ?;
169199 } else if ( b >= b'\x01' && b <= b'\x1F' ) || b == b'\x7F' {
170- write ! ( dest , " \\ {:x} " , b ) ?;
200+ hex_escape ( b , dest ) ?;
171201 } else {
172- write ! ( dest , " \\ {}" , b as char ) ?;
202+ char_escape ( b , dest ) ?;
173203 }
174204 chunk_start = i + 1 ;
175205 }
@@ -187,9 +217,9 @@ fn serialize_unquoted_url<W>(value: &str, dest: &mut W) -> fmt::Result where W:f
187217 } ;
188218 dest. write_str ( & value[ chunk_start..i] ) ?;
189219 if hex {
190- write ! ( dest , " \\ {:X} " , b ) ?;
220+ hex_escape ( b , dest ) ?;
191221 } else {
192- write ! ( dest , " \\ {}" , b as char ) ?;
222+ char_escape ( b , dest ) ?;
193223 }
194224 chunk_start = i + 1 ;
195225 }
@@ -247,7 +277,7 @@ impl<'a, W> fmt::Write for CssStringWriter<'a, W> where W: fmt::Write {
247277 self . inner . write_str ( & s[ chunk_start..i] ) ?;
248278 match escaped {
249279 Some ( x) => self . inner . write_str ( x) ?,
250- None => write ! ( self . inner, " \\ {:x} " , b ) ?,
280+ None => hex_escape ( b , self . inner ) ?,
251281 } ;
252282 chunk_start = i + 1 ;
253283 }
@@ -265,7 +295,8 @@ macro_rules! impl_tocss_for_int {
265295 impl <W : fmt:: Write > io:: Write for AssumeUtf8 <W > {
266296 #[ inline]
267297 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( ) ) ;
269300 self . 0 . write_str( unsafe { str :: from_utf8_unchecked( buf) } )
270301 . map_err( |_| io:: ErrorKind :: Other . into( ) )
271302 }
0 commit comments