1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
//! Provides features for parsing [Huffman code] table provided by the [HPACK] //! documentation. //! //! [HPACK] provides a pre-created [Huffman code] table for encoding [ASCII] //! characters to the Huffman sequence. This Huffman code was generated from //! statistics obtained on a large sample of HTTP headers. //! //! The parser module is responsible for parsing the [Huffman code] table into //! the static Rust source code. This module was used to create the ENCODE_TABLE //! constant which can be found in the `encode::table` module. //! //! You will probably never use this module while developing applications. //! //! [ASCII]: https://en.wikipedia.org/wiki/ASCII //! [HPACK]: https://tools.ietf.org/html/rfc7541 //! [Huffman code]: https://tools.ietf.org/html/rfc7541#appendix-B /// Parses the HPACK's static Huffman table. The function expects data to be in /// format as provided by the spec (7.2). /// /// **Example:** /// /// ```rust /// use std::fs; /// use std::path::Path; /// use httlib_huffman::parser::parse; /// /// let path = Path::new("assets/hpack-huffman.txt"); /// let data = fs::read_to_string(path).expect("Can't read file."); /// let codings = parse(&data); /// ``` pub fn parse(data: &str) -> Vec<(u16, u32)> { let lines = data.lines(); let mut codings = vec![]; for line in lines { let coding = parse_line(line); codings.push(coding); } codings } /// Parses a single line of the static Huffman table. The output returned /// contains a tuple of the number of bits for the code representing the symbol /// and Huffman LSB value. fn parse_line(line: &str) -> (u16, u32) { let mut msb = vec![]; for &b in &line.as_bytes()[12..45] { match b { b'1' => msb.push(true), b'0' => msb.push(false), b'|' | b' ' => {} _ => panic!("unexpected byte; {:?}", b), } } let lsb = u32::from_str_radix(&line[50..59].trim().to_string(), 16).expect("Invalid hex"); let len = msb.len() as u16; (len, lsb) } #[cfg(test)] mod tests { use std::fs; use std::path::Path; use super::*; /// Should read the text file `assets/hpack-huffman.txt` and parse the /// content into 2-dimensional table that can be used in Rust code. #[test] fn parses_huffman_table() { let path = Path::new("assets/hpack-huffman.txt"); let data = fs::read_to_string(path).expect("Can't read file."); let table = parse(&data); assert_eq!(table.len(), 257); let item = table[10]; assert_eq!(item.0, 30); assert_eq!(item.1, 0x3ffffffc); let item = table[32]; assert_eq!(item.0, 6); assert_eq!(item.1, 0x14); let item = table.last().unwrap(); assert_eq!(item.0, 30); assert_eq!(item.1, 0x3fffffff); } }