pub mod matchfinder;
use std::io::Write;
use lzma_rust2::{LzmaOptions, LzmaWriter};
use crate::decode::header::Properties;
use crate::error::{LazippyError, LazippyResult};
pub fn encode(input: &[u8], props: Properties) -> LazippyResult<Vec<u8>> {
let mut out = Vec::new();
let options = props_to_options(&props);
let props_byte = options.get_props();
out.push(props_byte);
out.extend_from_slice(&options.dict_size.to_le_bytes());
let uncomp_size: u64 = props.uncompressed_size.unwrap_or(u64::MAX);
out.extend_from_slice(&uncomp_size.to_le_bytes());
let compressed = encode_raw(input, &options)?;
out.extend_from_slice(&compressed);
Ok(out)
}
pub fn encode_7z(input: &[u8], dict_size: u32) -> LazippyResult<(Vec<u8>, Vec<u8>)> {
let options = LzmaOptions {
dict_size,
lc: LzmaOptions::LC_DEFAULT,
lp: LzmaOptions::LP_DEFAULT,
pb: LzmaOptions::PB_DEFAULT,
..LzmaOptions::with_preset(6)
};
let props_byte = options.get_props();
let mut props_blob = Vec::with_capacity(5);
props_blob.push(props_byte);
props_blob.extend_from_slice(&dict_size.to_le_bytes());
let compressed = encode_raw(input, &options)?;
Ok((props_blob, compressed))
}
fn encode_raw(input: &[u8], options: &LzmaOptions) -> LazippyResult<Vec<u8>> {
let mut buf = Vec::new();
{
let mut writer = LzmaWriter::new_no_header(&mut buf, options, true)
.map_err(|e| LazippyError::Backend(e.to_string()))?;
writer
.write_all(input)
.map_err(|e| LazippyError::Backend(e.to_string()))?;
let _ = writer
.finish()
.map_err(|e| LazippyError::Backend(e.to_string()))?;
}
Ok(buf)
}
fn props_to_options(props: &Properties) -> LzmaOptions {
LzmaOptions {
dict_size: props.dict_size.max(4096),
lc: props.lc as u32,
lp: props.lp as u32,
pb: props.pb as u32,
..LzmaOptions::with_preset(6)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::decode::header::Properties;
fn default_props() -> Properties {
Properties {
lc: 3,
lp: 0,
pb: 2,
dict_size: 1 << 16,
uncompressed_size: None,
}
}
#[test]
fn encode_empty_succeeds() {
let result = encode(&[], default_props());
assert!(result.is_ok(), "encode empty failed: {result:?}");
assert!(result.unwrap().len() >= 13);
}
#[test]
fn encode_nonempty_succeeds() {
let input = b"Hello, LZMA world!";
let result = encode(input, default_props());
assert!(result.is_ok(), "encode failed: {result:?}");
}
}