// Copyright (C) 2019, Cloudflare, Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use crate::octets; use super::Error; use super::Result; use self::table::DECODE_TABLE; use self::table::ENCODE_TABLE; pub fn decode(b: &mut octets::Octets) -> Result> { // Max compression ratio is >= 0.5 let mut out = Vec::with_capacity(b.len() << 1); let mut decoder = Decoder::new(); while b.cap() > 0 { let byte = b.get_u8()?; if let Some(b) = decoder.decode4(byte >> 4)? { out.push(b); } if let Some(b) = decoder.decode4(byte & 0xf)? { out.push(b); } } if !decoder.is_final() { return Err(Error::InvalidHuffmanEncoding); } Ok(out) } pub fn encode(src: &[u8], out: &mut octets::OctetsMut, low: bool) -> Result<()> { let mut bits: u64 = 0; let mut bits_left = 40; for &b in src { let b = if low { b.to_ascii_lowercase() } else { b }; let (nbits, code) = ENCODE_TABLE[b as usize]; bits |= code << (bits_left - nbits); bits_left -= nbits; while bits_left <= 32 { out.put_u8((bits >> 32) as u8)?; bits <<= 8; bits_left += 8; } } if bits_left != 40 { // This writes the EOS token bits |= (1 << bits_left) - 1; out.put_u8((bits >> 32) as u8)?; } Ok(()) } pub fn encode_output_length(src: &[u8], low: bool) -> Result { let mut bits: usize = 0; for &b in src { let b = if low { b.to_ascii_lowercase() } else { b }; let (nbits, _) = ENCODE_TABLE[b as usize]; bits += nbits; } let mut len = bits / 8; if bits & 7 != 0 { len += 1; } Ok(len) } struct Decoder { state: usize, maybe_eos: bool, } impl Decoder { fn new() -> Decoder { Decoder { state: 0, maybe_eos: false, } } // Decodes 4 bits fn decode4(&mut self, input: u8) -> Result> { const MAYBE_EOS: u8 = 1; const DECODED: u8 = 2; const ERROR: u8 = 4; // (next-state, byte, flags) let (next, byte, flags) = DECODE_TABLE[self.state][input as usize]; if flags & ERROR == ERROR { // Data followed the EOS marker return Err(Error::InvalidHuffmanEncoding); } let ret = if flags & DECODED == DECODED { Some(byte) } else { None }; self.state = next; self.maybe_eos = flags & MAYBE_EOS == MAYBE_EOS; Ok(ret) } fn is_final(&self) -> bool { self.state == 0 || self.maybe_eos } } mod table;