@@ -72,27 +72,39 @@ pub fn decode(src: &[u8], buf: &mut BytesMut) -> Result<BytesMut, DecoderError>
7272}
7373
7474pub fn encode ( src : & [ u8 ] , dst : & mut BytesMut ) {
75- let mut bits: u64 = 0 ;
76- let mut bits_left = 40 ;
75+ let mut bits = 0u64 ;
76+ let mut bits_len = 0 ;
7777
7878 for & b in src {
7979 let ( nbits, code) = ENCODE_TABLE [ b as usize ] ;
8080
81- bits |= code << ( bits_left - nbits) ;
82- bits_left - = nbits;
81+ bits = ( bits << nbits) | code ;
82+ bits_len + = nbits;
8383
84- while bits_left <= 32 {
85- dst. put_u8 ( ( bits >> 32 ) as u8 ) ;
84+ if bits_len >= 32 {
85+ let remaining = bits_len - 32 ;
86+ dst. put_u32 ( ( bits >> remaining) as u32 ) ;
8687
87- bits <<= 8 ;
88- bits_left += 8 ;
88+ bits_len = remaining;
89+ if remaining == 0 {
90+ bits = 0 ;
91+ } else {
92+ bits &= ( 1 << remaining) - 1 ;
93+ }
8994 }
9095 }
9196
92- if bits_left != 40 {
93- // This writes the EOS token
94- bits |= ( 1 << bits_left) - 1 ;
95- dst. put_u8 ( ( bits >> 32 ) as u8 ) ;
97+ if bits_len != 0 {
98+ // Pad the final byte with the EOS prefix (all ones).
99+ let padding = 8 - ( bits_len % 8 ) ;
100+ let padding = if padding == 8 { 0 } else { padding } ;
101+ bits = ( bits << padding) | ( ( 1 << padding) - 1 ) ;
102+ bits_len += padding;
103+
104+ while bits_len != 0 {
105+ bits_len -= 8 ;
106+ dst. put_u8 ( ( bits >> bits_len) as u8 ) ;
107+ }
96108 }
97109}
98110
@@ -141,6 +153,18 @@ mod test {
141153 assert_eq ! ( & dst[ ..] , & [ ( 0x21 << 2 ) + 3 ] ) ;
142154 }
143155
156+ #[ test]
157+ fn encode_rfc_example ( ) {
158+ let mut dst = BytesMut :: new ( ) ;
159+
160+ encode ( b"www.example.com" , & mut dst) ;
161+
162+ assert_eq ! (
163+ & dst[ ..] ,
164+ & [ 0xf1 , 0xe3 , 0xc2 , 0xe5 , 0xf2 , 0x3a , 0x6b , 0xa0 , 0xab , 0x90 , 0xf4 , 0xff ]
165+ ) ;
166+ }
167+
144168 #[ test]
145169 fn encode_decode_str ( ) {
146170 const DATA : & [ & str ] = & [
@@ -233,6 +257,45 @@ mod bench {
233257 });
234258 }
235259
260+ fn encode_input(b: &mut Bencher, input: &[u8]) {
261+ let mut encoded = BytesMut::new();
262+ encode(input, &mut encoded);
263+
264+ b.bytes = input.len() as u64;
265+ b.iter(|| {
266+ encoded.clear();
267+ encode(black_box(input), &mut encoded);
268+ black_box(encoded.as_ref());
269+ });
270+ }
271+
272+ #[bench]
273+ fn encode_short_ascii(b: &mut Bencher) {
274+ encode_input(b, b"www.example.com");
275+ }
276+
277+ #[bench]
278+ fn encode_header_value(b: &mut Bencher) {
279+ encode_input(
280+ b,
281+ b"text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8",
282+ );
283+ }
284+
285+ #[bench]
286+ fn encode_long_ascii(b: &mut Bencher) {
287+ encode_input(
288+ b,
289+ b"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0",
290+ );
291+ }
292+
293+ #[bench]
294+ fn encode_all_octets(b: &mut Bencher) {
295+ let input: Vec<_> = (0..=u8::MAX).collect();
296+ encode_input(b, &input);
297+ }
298+
236299 #[bench]
237300 fn decode_short_ascii(b: &mut Bencher) {
238301 decode_input(b, b"www.example.com");
0 commit comments