xpress_rs 0.1.2

Xpress implementation in Rust
Documentation
[![Documentation](https://docs.rs/xpress_rs/badge.svg)](https://docs.rs/xpress_rs)
[![Crates.io](https://img.shields.io/crates/v/xpress_rs.svg)](https://crates.io/crates/xpress_rs)
[![dependency status](https://deps.rs/crate/xpress_rs/0.1.1/status.svg)](https://deps.rs/crate/xpress_rs/0.1.1)
[![Rust](https://github.com/rthidfrev/Xpress_rs/actions/workflows/rust.yml/badge.svg)](https://github.com/rthidfrev/Xpress_rs/actions/workflows/rust.yml)
[![rust-clippy analyze](https://github.com/rthidfrev/Xpress_rs/actions/workflows/rust-clippy.yml/badge.svg)](https://github.com/rthidfrev/Xpress_rs/actions/workflows/rust-clippy.yml)
[![DevSkim](https://github.com/rthidfrev/Xpress_rs/actions/workflows/devskim.yml/badge.svg)](https://github.com/rthidfrev/Xpress_rs/actions/workflows/devskim.yml)


# Xpress_rs 

A rust implementation of the xpress compression algorithm. Defined in the [MS-XCA](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-XCA/%5bMS-XCA%5d.pdf)

Work in progress, only the LZ77 algorithm is implemented.

## LZ77 :

- [x] Comment
- [ ] Doc
- [ ] Rewrite tests
- [ ] Add benchmark
- [x] logging 
- [ ] optimization :
  - [ ] use other hashmap implementation
  - [ ] Make a custom hashmap implementation with hash function
  - [ ] Try chained hashmap, multiple hashmap and trees
  - [ ] Try to avoid hashmap reallocation (use a fixed size hashmap)
  - [ ] Global code optimization


### Logging


The logging feature use a lot of macro, so the execution time is not optimal.
I recommend to disable the logging feature in release mode, but can be useful for testing or debugging. 
- Use "cargo test --features logging" to enable logging in test
- Future release will have more logging feature (ex: only compile log macro you need)

### Error handling


The error handling is not optimal, and can be improved.

In the compression algorithm, the output buffer is a fixed size buffer, is defined to be 2 times the size of the input buffer.
Im not sure if this can result in a buffer overflow. 
I didn't check size in the algorithm, because it will slow down the algorithm and i didn't want to use vector for avoiding reallocation.
--> TODO: find a better way to implement this.

### Example


```rust
use xpress_rs::lz77::{LZ77Compressor,LZ77Decompressor};
use std::error::Error;

#[cfg(feature = "logging")]

 {
use env_logger::Env;
use log::{info, LevelFilter}; 
env_logger::Builder::new().filter(None, LevelFilter::Info).init();
}

// data to compress
let data_to_compress: Vec<u8> = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.".to_vec();

// init the Compressor
let compressor = LZ77Compressor::new(data_to_compress);

// compress the data
let result: Result<Vec<u8>,Box<dyn Error>> = compressor.compress();

// check if the compression is successful
match result {
    Ok(compressed_data) => {
        // init the Decompressor
        let decompressor = LZ77Decompressor::new(compressed_data);

        // decompress the data
        let result: Result<Vec<u8>,Box<dyn Error>> = decompressor.decompress();

        // check if the decompression is successful
        match result {
            Ok(decompressed_data) => {
                println!("Decompressed data: {:?}",decompressed_data);
            },
            Err(e) => {
                println!("Error: {}",e);
            }
        }
    },
    Err(e) => {
        println!("Error: {}",e);
    }
}

```