From fb28bb882ebccce1bb88ff35424bda1a8b3fcb0b Mon Sep 17 00:00:00 2001 From: mehbark Date: Sun, 5 Oct 2025 12:57:48 -0400 Subject: [PATCH] speed up Huffman encoding we compute the bits for each byte in advance --- src/huffman.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/huffman.rs b/src/huffman.rs index 7d80e75..fb8e2ee 100644 --- a/src/huffman.rs +++ b/src/huffman.rs @@ -1,4 +1,5 @@ use std::{ + array, collections::{BinaryHeap, HashMap}, fmt, }; @@ -21,8 +22,15 @@ impl CompressionScheme for Huffman { let tree = Node::build(&counts)?; + #[allow(clippy::cast_possible_truncation, reason = "byte is in 0..256")] + let byte_mapping: [_; 256] = array::from_fn(|byte| { + let mut buf = BitVec::new(); + tree.encode_byte(byte as u8, &mut buf); + buf + }); + for &byte in src { - tree.encode_byte(byte, buf); + buf.extend_from_bitslice(&byte_mapping[byte as usize]); } Some(tree) @@ -62,16 +70,13 @@ impl Node { } /// Write to `buf` the sequence of bits that this tree has assigned `byte`. - /// - /// # Panics - /// Panics if called with a byte that was not passed to [`build`]. fn encode_byte(&self, byte: u8, buf: &mut BitVec) { let mut current = self; loop { match current { Node::Leaf { byte: _ } => break, Node::Branch { path0, path1 } => { - // TODO: this contains check is wasteful. be less dumb? + // wasteful, but we precompute a table, so it's fine :D if path0.contains(byte) { buf.push(false); current = path0;