huffman_rust/
lib.rs

1extern crate byteorder;
2
3use std::io::{Read, Seek, SeekFrom, Write, BufReader, BufWriter};
4use std::error::Error;
5
6use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian};
7
8mod bitstream;
9use bitstream::*;
10
11mod huffman;
12pub use huffman::*;
13
14mod canonical;
15pub use canonical::*;
16
17const NUM_BYTES: usize = 256;
18
19pub fn buffered_encode<R: Read + Seek, W: Write>(read: R, write: W) -> Result<(), Box<Error>> {
20    encode(BufReader::new(read), BufWriter::new(write))
21}
22
23pub fn buffered_decode<R: Read, W: Write>(read: R, write: W) -> Result<(), Box<Error>> {
24    decode(BufReader::new(read), BufWriter::new(write))
25}
26
27pub fn encode<R: Read + Seek, W: Write>(mut read: R, mut write: W) -> Result<(), Box<Error>> {
28    // Build a canonical huffman tree from read
29    let tree = CanonicalTree::from_read(read.by_ref())?;
30
31    // Write the size of the original file
32    write.write_u64::<LittleEndian>(tree.bytes)?;
33
34    // Create a buffer for the code lengths
35    let mut code_buf = [0; 256];
36
37    // Write out the code lengths
38    for i in 0..code_buf.len() {
39        code_buf[i] = tree.code_book.get(&(i as u8))
40            .map(|v| v.len() as u8)
41            .unwrap_or(0);
42    }
43
44    write.write(&code_buf)?;
45
46    // Reset the read
47    read.seek(SeekFrom::Start(0))?;
48
49    // Encode using canonical tree
50    tree.encode(&mut read, &mut write)?;
51
52    Ok(())
53}
54
55pub fn decode<R: Read, W: Write>(mut read: R, mut write: W) -> Result<(), Box<Error>> {
56    // Read the size of the original file
57    let bytes: u64 = read.read_u64::<LittleEndian>()?;
58
59    // Read in code lengths
60    let mut code_buf = [0; 256];
61    read.read_exact(&mut code_buf)?;
62
63    let code_lengths: Vec<(u8, u8)> = code_buf.iter().enumerate()
64        .map(|(i, &l)| (i as u8, l))
65        .collect();
66
67    let tree = CanonicalTree::new(bytes, code_lengths);
68
69    tree.decode(&mut read, &mut write)?;
70
71    Ok(())
72}
73
74#[cfg(test)]
75mod tests {
76    #[test]
77    fn it_works() {
78        assert_eq!(2 + 2, 4);
79    }
80}