use bit_vec::BitVec;
use std::io::{Cursor,Read,Write,Seek,SeekFrom,BufReader,BufWriter,Bytes};
use crate::DYNERR;
const WIN_SIZE: usize = 4096; const LOOKAHEAD: usize = 60; const THRESHOLD: usize = 2; const NIL: usize = WIN_SIZE;
const N_CHAR: usize = 256 - THRESHOLD + LOOKAHEAD; const TAB_SIZE: usize = N_CHAR * 2 - 1; const ROOT: usize = TAB_SIZE - 1; const MAX_FREQ: usize = 0x8000;
const P_LEN: [u8;64] = [
0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
];
const P_CODE: [u8;64] = [
0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
];
const D_LEN: [u8;256] = [
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
];
const D_CODE: [u8;256] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
];
struct LZSS {
dictionary: Vec<u8>,
match_position: i32,
match_length: usize,
lson: Vec<usize>,
rson: Vec<usize>,
dad: Vec<usize>,
}
struct AdaptiveHuffman {
bits: BitVec,
ptr: usize,
count: usize,
freq: Vec<usize>,
prnt: Vec<usize>,
son: Vec<usize>
}
impl LZSS {
fn new() -> Self {
Self {
dictionary: vec![0;WIN_SIZE+LOOKAHEAD-1],
match_position: 0,
match_length: 0,
lson: vec![0;WIN_SIZE+1],
rson: vec![0;WIN_SIZE+257],
dad: vec![0;WIN_SIZE+1]
}
}
fn init_tree(&mut self) {
for i in WIN_SIZE+1..=WIN_SIZE+256 {
self.rson[i] = NIL; }
for i in 0..WIN_SIZE {
self.dad[i] = NIL; }
}
fn insert_node(&mut self,r: usize) {
let mut cmp: i16 = 1;
let key = &self.dictionary[r..];
let mut p = WIN_SIZE + 1 + key[0] as usize;
self.rson[r] = NIL;
self.lson[r] = NIL;
self.match_length = 0;
loop {
if cmp>=0 {
if self.rson[p] != NIL {
p = self.rson[p];
} else {
self.rson[p] = r;
self.dad[r] = p;
return;
}
} else {
if self.lson[p] != NIL {
p = self.lson[p];
} else {
self.lson[p] = r;
self.dad[r] = p;
return;
}
}
let mut i: usize = 1;
while i < LOOKAHEAD {
cmp = key[i] as i16 - self.dictionary[p+i] as i16;
if cmp != 0 {
break;
}
i += 1;
}
if i > THRESHOLD {
if i > self.match_length {
self.match_position = ((r as i32 - p as i32) & (WIN_SIZE as i32 - 1)) - 1;
self.match_length = i;
if self.match_length >= LOOKAHEAD {
break;
}
}
if i==self.match_length {
let c = ((r as i32 - p as i32) & (WIN_SIZE as i32 - 1)) - 1;
if c < self.match_position {
self.match_position = c;
}
}
}
}
self.dad[r] = self.dad[p];
self.lson[r] = self.lson[p];
self.rson[r] = self.rson[p];
self.dad[self.lson[p]] = r;
self.dad[self.rson[p]] = r;
if self.rson[self.dad[p]] == p {
self.rson[self.dad[p]] = r;
} else {
self.lson[self.dad[p]] = r;
}
self.dad[p] = NIL; }
fn delete_node(&mut self,p: usize) {
let mut q;
if self.dad[p] == NIL {
return; }
if self.rson[p] == NIL {
q = self.lson[p]; } else if self.lson[p] == NIL {
q = self.rson[p]; } else {
q = self.lson[p];
if self.rson[q] != NIL {
loop {
q = self.rson[q];
if self.rson[q] == NIL {
break;
}
}
self.rson[self.dad[q]] = self.lson[q];
self.dad[self.lson[q]] = self.dad[q];
self.lson[q] = self.lson[p];
self.dad[self.lson[p]] = q;
}
self.rson[q] = self.rson[p];
self.dad[self.rson[p]] = q;
}
self.dad[q] = self.dad[p];
if self.rson[self.dad[p]] == p {
self.rson[self.dad[p]] = q;
} else {
self.lson[self.dad[p]] = q;
}
self.dad[p] = NIL;
}
}
impl AdaptiveHuffman {
fn new() -> Self {
Self {
bits: BitVec::new(),
ptr: 0,
count: 0,
freq: vec![0;TAB_SIZE+1], prnt: vec![0;TAB_SIZE+N_CHAR], son: vec![0;TAB_SIZE]
}
}
fn drop_leading_bits(&mut self) {
let cpy = self.bits.clone();
self.bits = BitVec::new();
for i in self.ptr..cpy.len() {
self.bits.push(cpy.get(i).unwrap());
}
self.ptr = 0;
}
fn start_huff(&mut self) {
for i in 0..N_CHAR {
self.freq[i] = 1;
self.son[i] = i + TAB_SIZE;
self.prnt[i+TAB_SIZE] = i;
}
let mut i = 0;
let mut j = N_CHAR;
while j <= ROOT {
self.freq[j] = self.freq[i] + self.freq[i+1];
self.son[j] = i;
self.prnt[i] = j;
self.prnt[i+1] = j;
i += 2;
j += 1;
}
self.freq[TAB_SIZE] = 0xffff;
self.prnt[ROOT] = 0;
}
fn rebuild_huff(&mut self) {
let mut j = 0;
for i in 0..TAB_SIZE {
if self.son[i] >= TAB_SIZE {
self.freq[j] = (self.freq[i] + 1)/2;
self.son[j] = self.son[i];
j += 1;
}
}
let mut i: usize = 0; j = N_CHAR; let mut k: usize; let mut f: usize; let mut l: usize; while j < TAB_SIZE {
k = i + 1;
f = self.freq[i] + self.freq[k];
self.freq[j] = f;
k = j - 1;
while f < self.freq[k] {
k -= 1;
}
k += 1;
l = (j - k)*2;
for kp in (k..k+l).rev() {
self.freq[kp+1] = self.freq[kp]
}
self.freq[k] = f;
for kp in (k..k+l).rev() {
self.son[kp+1] = self.son[kp]
}
self.son[k] = i;
i += 2; j += 1; }
for i in 0..TAB_SIZE {
k = self.son[i];
if k >= TAB_SIZE {
self.prnt[k] = i;
} else {
self.prnt[k] = i;
self.prnt[k+1] = i;
}
}
}
fn update(&mut self,c0: i16) {
let mut i: usize;
let mut j: usize;
let mut k: usize;
let mut l: usize;
if self.freq[ROOT] == MAX_FREQ {
self.rebuild_huff()
}
let mut c = self.prnt[(c0 as i32 + TAB_SIZE as i32) as usize];
loop {
self.freq[c] += 1;
k = self.freq[c];
l = c + 1;
if k > self.freq[l] {
while k > self.freq[l] {
l += 1;
}
l -= 1;
self.freq[c] = self.freq[l];
self.freq[l] = k;
i = self.son[c];
self.prnt[i] = l;
if i<TAB_SIZE {
self.prnt[i+1] = l;
}
j = self.son[l];
self.son[l] = i;
self.prnt[j] = c;
if j<TAB_SIZE {
self.prnt[j+1] = c;
}
self.son[c] = j;
c = l;
}
c = self.prnt[c];
if c==0 {
break; }
}
}
fn get_bit<R: Read>(&mut self,bytes: &mut Bytes<R>) -> u8 {
match self.bits.get(self.ptr) {
Some(bit) => {
self.ptr += 1;
bit as u8
},
None => {
match bytes.next() {
Some(Ok(by)) => {
if self.bits.len()>512 {
self.drop_leading_bits();
}
self.bits.append(&mut BitVec::from_bytes(&[by]));
self.count += 1;
self.get_bit(bytes)
}
Some(Err(e)) => {
panic!("error reading file {}",e)
},
None => 0
}
}
}
}
fn get_byte<R: Read>(&mut self,bytes: &mut Bytes<R>) -> u8 {
let mut ans: u8 = 0;
for _i in 0..8 {
ans <<= 1;
ans |= self.get_bit(bytes);
}
ans
}
fn put_code<W: Write + Seek>(&mut self,num_bits: u16,mut code: u16,writer: &mut BufWriter<W>) {
for _i in 0..num_bits {
self.bits.push(code & 0x8000 > 0);
code <<= 1;
self.ptr += 1;
}
let bytes = self.bits.to_bytes();
writer.write(&bytes.as_slice()).expect("write err");
if self.bits.len() % 8 > 0 {
writer.seek(SeekFrom::Current(-1)).expect("seek err");
self.ptr = 8 * (self.bits.len() / 8);
self.drop_leading_bits();
} else {
self.bits = BitVec::new();
self.ptr = 0;
}
}
fn encode_char<W: Write + Seek>(&mut self,c: u16,writer: &mut BufWriter<W>) {
let mut i: u16 = 0;
let mut j: u16 = 0;
let mut k: usize = self.prnt[c as usize + TAB_SIZE];
loop {
i >>= 1;
if k & 1 > 0 {
i += 0x8000;
}
j += 1;
k = self.prnt[k];
if k==ROOT {
break;
}
}
self.put_code(j,i,writer);
self.update(c as i16); }
fn encode_position<W: Write + Seek>(&mut self,c: u16,writer: &mut BufWriter<W>) {
let i = (c >> 6) as usize;
self.put_code(P_LEN[i] as u16,(P_CODE[i] as u16) << 8,writer);
self.put_code(6,(c & 0x3f) << 10,writer);
}
fn decode_char<R: Read>(&mut self,bytes: &mut Bytes<R>) -> i16 {
let mut c: usize = self.son[ROOT];
while c < TAB_SIZE {
c += self.get_bit(bytes) as usize;
c = self.son[c];
}
c -= TAB_SIZE;
self.update(c as i16); c as i16
}
fn decode_position<R: Read>(&mut self,bytes: &mut Bytes<R>) -> u16 {
let mut first8 = self.get_byte(bytes) as u16;
let upper6 = (D_CODE[first8 as usize] as u16) << 6;
let coded_bits = D_LEN[first8 as usize] as u16;
for _i in 0..coded_bits-2 {
first8 <<= 1;
first8 += self.get_bit(bytes) as u16;
}
upper6 | (first8 & 0x3f)
}
}
pub fn encode<R: Read + Seek, W: Write + Seek>(expanded_in: &mut R, compressed_out: &mut W) -> Result<(u64,u64),DYNERR> {
let mut reader = BufReader::new(expanded_in);
let mut writer = BufWriter::new(compressed_out);
let expanded_length = reader.seek(SeekFrom::End(0))?;
if expanded_length >= u32::MAX as u64 {
return Err(Box::new(crate::Error::FileTooLarge));
}
let header = u32::to_le_bytes(expanded_length as u32);
writer.write(&header)?;
reader.seek(SeekFrom::Start(0))?;
let mut bytes = reader.bytes();
let mut lzss = LZSS::new();
let mut huff = AdaptiveHuffman::new();
huff.start_huff();
lzss.init_tree();
let mut s = 0;
let mut r = WIN_SIZE - LOOKAHEAD;
for i in s..r {
lzss.dictionary[i] = b' ';
}
let mut len = 0;
while len < LOOKAHEAD {
match bytes.next() {
Some(Ok(c)) => {
lzss.dictionary[r+len] = c;
len += 1;
},
None => {
break;
},
Some(Err(e)) => {
return Err(Box::new(e));
}
}
}
for i in 1..=LOOKAHEAD {
lzss.insert_node(r-i);
}
lzss.insert_node(r);
loop {
if lzss.match_length > len {
lzss.match_length = len;
}
if lzss.match_length <= THRESHOLD {
lzss.match_length = 1;
huff.encode_char(lzss.dictionary[r] as u16,&mut writer);
} else {
huff.encode_char((255-THRESHOLD+lzss.match_length) as u16,&mut writer);
huff.encode_position(lzss.match_position as u16,&mut writer);
}
let last_match_length = lzss.match_length;
let mut i = 0;
while i < last_match_length {
let c = match bytes.next() {
Some(Ok(c)) => c,
None => break,
Some(Err(e)) => return Err(Box::new(e))
};
lzss.delete_node(s);
lzss.dictionary[s] = c;
if s < LOOKAHEAD - 1 {
lzss.dictionary[s+WIN_SIZE] = c;
}
s = (s+1) & (WIN_SIZE-1);
r = (r+1) & (WIN_SIZE-1);
lzss.insert_node(r);
i += 1;
}
while i < last_match_length {
lzss.delete_node(s);
s = (s+1) & (WIN_SIZE-1);
r = (r+1) & (WIN_SIZE-1);
len -= 1;
if len > 0 {
lzss.insert_node(r);
}
i += 1;
}
if len <= 0 {
break;
}
}
writer.seek(SeekFrom::End(0))?; writer.flush()?;
Ok((expanded_length,writer.stream_position()?))
}
pub fn decode<R: Read + Seek , W: Write + Seek>(compressed_in: &mut R, expanded_out: &mut W) -> Result<(u64,u64),DYNERR>
{
let mut reader = BufReader::new(compressed_in);
let mut writer = BufWriter::new(expanded_out);
let mut header: [u8;4] = [0;4];
reader.read_exact(&mut header)?;
let textsize = u32::from_le_bytes(header);
let mut bytes = reader.bytes();
let mut huff = AdaptiveHuffman::new();
let mut lzss= LZSS::new();
huff.start_huff();
for i in 0..WIN_SIZE - LOOKAHEAD {
lzss.dictionary[i] = b' ';
}
let mut r = WIN_SIZE - LOOKAHEAD;
while writer.stream_position()? < textsize as u64 {
let c = huff.decode_char(&mut bytes);
if c < 256 {
writer.write(&[c as u8])?;
lzss.dictionary[r] = c as u8;
r += 1;
r &= WIN_SIZE - 1;
} else {
let strpos = ((r as i32 - huff.decode_position(&mut bytes) as i32 - 1) & (WIN_SIZE as i32 - 1)) as usize;
let strlen = c as usize + THRESHOLD - 255;
for k in 0..strlen {
let c8 = lzss.dictionary[(strpos + k) & (WIN_SIZE - 1)];
writer.write(&[c8])?;
lzss.dictionary[r] = c8;
r += 1;
r &= WIN_SIZE - 1;
}
}
}
writer.flush()?;
Ok((huff.count as u64,writer.stream_position()?))
}
pub fn decode_slice(slice: &[u8]) -> Result<Vec<u8>,DYNERR> {
let mut src = Cursor::new(slice);
let mut ans: Cursor<Vec<u8>> = Cursor::new(Vec::new());
decode(&mut src,&mut ans)?;
Ok(ans.into_inner())
}
pub fn encode_slice(slice: &[u8]) -> Result<Vec<u8>,DYNERR> {
let mut src = Cursor::new(slice);
let mut ans: Cursor<Vec<u8>> = Cursor::new(Vec::new());
encode(&mut src,&mut ans)?;
Ok(ans.into_inner())
}
#[test]
fn compression_works() {
let test_data = "12345123456789123456789\n".as_bytes();
let lzhuf_str = "18 00 00 00 DE EF B7 FC 0E 0C 70 13 85 C3 E2 71 64 81 19 60";
let compressed = encode_slice(test_data).expect("encoding failed");
assert_eq!(compressed,hex::decode(lzhuf_str.replace(" ","")).unwrap());
let test_data = "I am Sam. Sam I am. I do not like this Sam I am.\n".as_bytes();
let lzhuf_str = "31 00 00 00 EA EB 3D BF 9C 4E FE 1E 16 EA 34 09 1C 0D C0 8C 02 FC 3F 77 3F 57 20 17 7F 1F 5F BF C6 AB 7F A5 AF FE 4C 39 96";
let compressed = encode_slice(test_data).expect("encoding failed");
assert_eq!(compressed,hex::decode(lzhuf_str.replace(" ","")).unwrap());
}
#[test]
fn invertibility() {
let test_data = "I am Sam. Sam I am. I do not like this Sam I am.\n".as_bytes();
let compressed = encode_slice(test_data).expect("encoding failed");
let expanded = decode_slice(&compressed).expect("decoding failed");
assert_eq!(test_data.to_vec(),expanded);
let test_data = "1234567".as_bytes();
let compressed = encode_slice(test_data).expect("encoding failed");
let expanded = decode_slice(&compressed).expect("decoding failed");
assert_eq!(test_data.to_vec(),expanded[0..7]);
}