use bitvec::prelude::*;
use crate::{huffman::*, lz77::{lz77_decode, lz77_encode}};
use std::{cell::LazyCell, collections::HashMap, path::PathBuf};
use std::fs;
use std::fmt::Error;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Zpp {
filename: String,
huff_table: HashMap<u8, (u16, u8)>,
encoded: Vec<u8>,
binary_len: usize,
}
pub fn compress_file(source: &PathBuf) -> Result<f32, Error> {
let oldfilename = source.file_name().unwrap().to_str().ok_or(Error)?.to_string();
let mut newpathbuf = source.clone();
newpathbuf.set_extension("zpp");
let mut zpp = Zpp {
filename: oldfilename,
huff_table: HashMap::new(),
encoded: Vec::new(),
binary_len: 0,
};
let bytes = fs::read(source).map_err(|_| Error)?;
let lz77_encoded = lz77_encode(&bytes[..]);
let mut huff_coder = HuffmanTree::from_bytes(&lz77_encoded);
let code_dict = huff_coder.gen_dict();
let (encoded, len) = huff_encode(&lz77_encoded[..], &code_dict)?;
zpp.huff_table = code_dict;
zpp.encoded = encoded;
zpp.binary_len = len;
let serialized = bincode::serialize(&zpp).map_err(|_| Error)?;
let compression_ratio = bytes.len() as f32 / (serialized.len() as f32);
fs::write(newpathbuf, serialized).map_err(|_| Error)?;
Ok(compression_ratio)
}
pub fn decompress_file(source: &PathBuf) -> Result<(), Error> {
let serialized = fs::read(source).map_err(|_| Error)?;
let zpp: Zpp = bincode::deserialize(&serialized[..]).map_err(|_| Error)?;
let lz77_encoded = huff_decode(&zpp.encoded, &zpp.huff_table, zpp.binary_len).map_err(|_| Error)?;
let decoded = lz77_decode(&lz77_encoded)?;
fs::write(zpp.filename, decoded).map_err(|_| Error)?;
Ok(())
}