use std::io::{Read, Write};
use lz4_flex::frame::{FrameDecoder, FrameEncoder};
use crate::error::{Error, Result};
pub fn compress(src: &[u8]) -> Result<Vec<u8>> {
let mut encoder = FrameEncoder::new(Vec::new());
encoder
.write_all(src)
.map_err(|e| Error::InvalidLz4(e.to_string()))?;
encoder
.finish()
.map_err(|e| Error::InvalidLz4(e.to_string()))
}
pub fn uncompress(src: &[u8]) -> Result<Vec<u8>> {
let mut decoder = FrameDecoder::new(src);
let mut buffer = Vec::new();
decoder
.read_to_end(&mut buffer)
.map_err(|e| Error::InvalidLz4(e.to_string()))?;
Ok(buffer)
}
#[cfg(test)]
mod tests {
use super::{compress, uncompress};
use crate::error::Result;
#[test]
fn test_compress_and_uncompress_roundtrip() {
let msg = b"This is a test message for LZ4 compression";
let compressed = compress(msg).unwrap();
let decompressed = uncompress(&compressed).unwrap();
assert_eq!(msg.to_vec(), decompressed);
}
#[test]
fn test_uncompress_corrupted_data() {
let data = b"Hello, LZ4 compression!";
let mut compressed = compress(data).unwrap();
if compressed.len() > 7 {
compressed[7] ^= 0xFF;
}
let result: Result<Vec<u8>> = uncompress(&compressed);
assert!(result.is_err());
}
#[test]
fn test_empty_input() {
let empty = b"";
let compressed = compress(empty).unwrap();
let decompressed = uncompress(&compressed).unwrap();
assert!(decompressed.is_empty());
}
#[test]
fn test_large_input_compression_ratio() {
let data: Vec<u8> = (0..100_000).map(|i| (i % 256) as u8).collect();
let compressed = compress(&data).unwrap();
assert!(compressed.len() < data.len());
let decompressed = uncompress(&compressed).unwrap();
assert_eq!(data, decompressed);
}
#[test]
fn test_repetitive_data() {
let data = "aaaaaa".repeat(10_000).into_bytes();
let compressed = compress(&data).unwrap();
assert!(compressed.len() < data.len() / 2);
let decompressed = uncompress(&compressed).unwrap();
assert_eq!(data, decompressed);
}
#[test]
fn test_all_byte_values() {
let data: Vec<u8> = (0u8..=255).collect();
let compressed = compress(&data).unwrap();
let decompressed = uncompress(&compressed).unwrap();
assert_eq!(data, decompressed);
}
#[test]
fn test_frame_header_magic() {
let data = b"verify lz4 frame header";
let compressed = compress(data).unwrap();
assert!(compressed.len() >= 4);
assert_eq!(&compressed[0..4], &[0x04, 0x22, 0x4D, 0x18]);
}
#[test]
fn test_single_byte() {
let data = b"X";
let compressed = compress(data).unwrap();
let decompressed = uncompress(&compressed).unwrap();
assert_eq!(data.to_vec(), decompressed);
}
#[test]
fn test_non_repetitive_data() {
let data: Vec<u8> = (0u32..1_000)
.flat_map(|i| i.to_le_bytes())
.collect();
let compressed = compress(&data).unwrap();
let decompressed = uncompress(&compressed).unwrap();
assert_eq!(data, decompressed);
}
#[test]
fn test_lz4_compression_attribute_value() {
use crate::compression::Compression;
assert_eq!(Compression::LZ4 as i8, 3);
}
#[test]
fn test_invalid_frame_content() {
let mut invalid = vec![0x04, 0x22, 0x4D, 0x18];
invalid.extend_from_slice(&[0x40, 0x00, 0x00, 0x00]);
invalid.extend_from_slice(&[0x7F, 0xFF, 0xFF, 0xFF]);
let result: Result<Vec<u8>> = uncompress(&invalid);
assert!(result.is_err());
}
}