1mod table;
2
3use self::table::{DECODE_TABLE, ENCODE_TABLE};
4use crate::hpack::DecoderError;
5
6use bytes::{BufMut, BytesMut};
7
8const BRANCH: u16 = 0x8000;
9const TABLE_INDEX_MASK: u16 = 0x7f00;
10const TABLE_WIDTH: usize = 256;
11
12pub fn decode(src: &[u8], buf: &mut BytesMut) -> Result<BytesMut, DecoderError> {
13 buf.reserve(src.len() << 1);
15
16 let mut table = 0;
17 let mut acc = 0u32;
18 let mut bits = 0;
19
20 for &byte in src {
21 acc = (acc << 8) | byte as u32;
22 bits += 8;
23
24 while bits >= 8 {
25 let index = (acc >> (bits - 8)) as u8 as usize;
26 let entry = DECODE_TABLE[table * TABLE_WIDTH + index];
27
28 if entry & BRANCH == 0 {
29 buf.put_u8(entry as u8);
30 table = 0;
31 bits -= (entry >> 8) as usize;
32 } else {
33 table = ((entry & TABLE_INDEX_MASK) >> 8) as usize;
34 if table == 0 {
35 return Err(DecoderError::InvalidHuffmanCode);
36 }
37 bits -= 8;
38 }
39 }
40 }
41
42 while bits > 0 {
45 debug_assert!(bits < 8);
46 let padding = (1u32 << bits) - 1;
47 if table == 0 && acc & padding == padding {
48 break;
49 }
50
51 let index = (acc << (8 - bits)) as u8 as usize;
52 let entry = DECODE_TABLE[table * TABLE_WIDTH + index];
53 if entry & BRANCH != 0 {
54 return Err(DecoderError::InvalidHuffmanCode);
55 }
56
57 let used = (entry >> 8) as usize;
58 if used > bits {
59 return Err(DecoderError::InvalidHuffmanCode);
60 }
61
62 buf.put_u8(entry as u8);
63 table = 0;
64 bits -= used;
65 }
66
67 if table == 0 {
68 Ok(buf.split())
69 } else {
70 Err(DecoderError::InvalidHuffmanCode)
71 }
72}
73
74pub fn encode(src: &[u8], dst: &mut BytesMut) {
75 let mut bits: u64 = 0;
76 let mut bits_left = 40;
77
78 for &b in src {
79 let (nbits, code) = ENCODE_TABLE[b as usize];
80
81 bits |= code << (bits_left - nbits);
82 bits_left -= nbits;
83
84 while bits_left <= 32 {
85 dst.put_u8((bits >> 32) as u8);
86
87 bits <<= 8;
88 bits_left += 8;
89 }
90 }
91
92 if bits_left != 40 {
93 bits |= (1 << bits_left) - 1;
95 dst.put_u8((bits >> 32) as u8);
96 }
97}
98
99#[cfg(test)]
100mod test {
101 use super::*;
102
103 fn decode(src: &[u8]) -> Result<BytesMut, DecoderError> {
104 let mut buf = BytesMut::new();
105 super::decode(src, &mut buf)
106 }
107
108 #[test]
109 fn decode_single_byte() {
110 assert_eq!("o", decode(&[0b00111111]).unwrap());
111 assert_eq!("0", decode(&[7]).unwrap());
112 assert_eq!("A", decode(&[(0x21 << 2) + 3]).unwrap());
113 }
114
115 #[test]
116 fn single_char_multi_byte() {
117 assert_eq!("#", decode(&[255, 160 + 15]).unwrap());
118 assert_eq!("$", decode(&[255, 200 + 7]).unwrap());
119 assert_eq!("\x0a", decode(&[255, 255, 255, 240 + 3]).unwrap());
120 }
121
122 #[test]
123 fn multi_char() {
124 assert_eq!("!0", decode(&[254, 1]).unwrap());
125 assert_eq!(" !", decode(&[0b01010011, 0b11111000]).unwrap());
126 }
127
128 #[test]
129 fn encode_single_byte() {
130 let mut dst = BytesMut::with_capacity(1);
131
132 encode(b"o", &mut dst);
133 assert_eq!(&dst[..], &[0b00111111]);
134
135 dst.clear();
136 encode(b"0", &mut dst);
137 assert_eq!(&dst[..], &[7]);
138
139 dst.clear();
140 encode(b"A", &mut dst);
141 assert_eq!(&dst[..], &[(0x21 << 2) + 3]);
142 }
143
144 #[test]
145 fn encode_decode_str() {
146 const DATA: &[&str] = &[
147 "hello world",
148 ":method",
149 ":scheme",
150 ":authority",
151 "yahoo.co.jp",
152 "GET",
153 "http",
154 ":path",
155 "/images/top/sp2/cmn/logo-ns-130528.png",
156 "example.com",
157 "hpack-test",
158 "xxxxxxx1",
159 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0",
160 "accept",
161 "Accept",
162 "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
163 "cookie",
164 "B=76j09a189a6h4&b=3&s=0b",
165 "TE",
166 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi non bibendum libero. \
167 Etiam ultrices lorem ut.",
168 ];
169
170 for s in DATA {
171 let mut dst = BytesMut::with_capacity(s.len());
172
173 encode(s.as_bytes(), &mut dst);
174
175 let decoded = decode(&dst).unwrap();
176
177 assert_eq!(&decoded[..], s.as_bytes());
178 }
179 }
180
181 #[test]
182 fn encode_decode_u8() {
183 const DATA: &[&[u8]] = &[b"\0", b"\0\0\0", b"\0\x01\x02\x03\x04\x05", b"\xFF\xF8"];
184
185 for s in DATA {
186 let mut dst = BytesMut::with_capacity(s.len());
187
188 encode(s, &mut dst);
189
190 let decoded = decode(&dst).unwrap();
191
192 assert_eq!(&decoded[..], &s[..]);
193 }
194 }
195
196 #[test]
197 fn encode_decode_all_octets() {
198 let src: Vec<_> = (0..=u8::MAX).collect();
199 let mut encoded = BytesMut::new();
200 encode(&src, &mut encoded);
201 assert_eq!(decode(&encoded).unwrap(), src);
202 }
203
204 #[test]
205 fn rejects_eos_and_invalid_padding() {
206 assert_eq!(decode(&[0xff]), Err(DecoderError::InvalidHuffmanCode));
207 assert_eq!(
208 decode(&[0xff, 0xff, 0xff, 0xff]),
209 Err(DecoderError::InvalidHuffmanCode)
210 );
211 assert_eq!(decode(&[0]), Err(DecoderError::InvalidHuffmanCode));
212 }
213}
214
215