pub mod compress;
pub mod crc32c;
pub mod decompress;
pub mod error;
pub mod frame;
pub use compress::compress;
pub use compress::max_compress_len;
pub use decompress::decompress;
pub use decompress::get_decompress_len as decompress_len;
pub use error::SnappyError;
pub use frame::FrameDecoder;
pub use frame::FrameEncoder;
#[cfg(test)]
mod tests {
use super::*;
use std::io::{Read, Write};
#[test]
fn test_block_roundtrip_empty() {
let data: &[u8] = b"";
let compressed = compress(data);
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data);
}
#[test]
fn test_block_roundtrip_hello() {
let data = b"Hello, World!";
let compressed = compress(data);
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data);
}
#[test]
fn test_block_roundtrip_repeated() {
let data = vec![b'A'; 10_000];
let compressed = compress(&data);
assert!(
compressed.len() < data.len() / 2,
"compressed {} vs original {}",
compressed.len(),
data.len()
);
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data);
}
#[test]
fn test_block_roundtrip_pattern() {
let data = b"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
let compressed = compress(data);
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data.as_slice());
}
#[test]
fn test_block_roundtrip_binary() {
let data: Vec<u8> = (0..=255).cycle().take(4096).collect();
let compressed = compress(&data);
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data);
}
#[test]
fn test_block_roundtrip_single_byte() {
let data = [0x42];
let compressed = compress(&data);
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data);
}
#[test]
fn test_block_roundtrip_two_bytes() {
let data = [0x42, 0x43];
let compressed = compress(&data);
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data);
}
#[test]
fn test_block_roundtrip_three_bytes() {
let data = [0x42, 0x43, 0x44];
let compressed = compress(&data);
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data);
}
#[test]
fn test_decompress_len() {
let data = vec![0u8; 12345];
let compressed = compress(&data);
let len = decompress_len(&compressed).expect("should decode length");
assert_eq!(len, 12345);
}
#[test]
fn test_max_compress_len_bounds() {
for size in [0, 1, 100, 1000, 65536, 1_000_000] {
let max_len = max_compress_len(size);
let data = vec![0xFFu8; size];
let compressed = compress(&data);
assert!(
compressed.len() <= max_len,
"compressed {} > max {} for input size {}",
compressed.len(),
max_len,
size
);
}
}
#[test]
fn test_decompress_invalid_data() {
let garbage = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
let result = decompress(&garbage);
assert!(result.is_err());
}
#[test]
fn test_frame_roundtrip_various_sizes() {
for size in [0, 1, 10, 100, 1000, 65535, 65536, 65537, 100_000] {
let data: Vec<u8> = (0..size).map(|i| (i % 251) as u8).collect();
let mut compressed = Vec::new();
{
let mut encoder = FrameEncoder::new(&mut compressed);
encoder
.write_all(&data)
.unwrap_or_else(|e| panic!("write failed for size {size}: {e}"));
encoder
.finish()
.unwrap_or_else(|e| panic!("finish failed for size {size}: {e}"));
}
let mut decoder = FrameDecoder::new(&compressed[..]);
let mut output = Vec::new();
decoder
.read_to_end(&mut output)
.unwrap_or_else(|e| panic!("read failed for size {size}: {e}"));
assert_eq!(output, data, "roundtrip mismatch for size {size}");
}
}
#[test]
fn test_frame_multi_write_roundtrip() {
let mut compressed = Vec::new();
{
let mut encoder = FrameEncoder::new(&mut compressed);
encoder
.write_all(b"Part 1. ")
.expect("write should succeed");
encoder
.write_all(b"Part 2. ")
.expect("write should succeed");
encoder.write_all(b"Part 3.").expect("write should succeed");
encoder.finish().expect("finish should succeed");
}
let mut decoder = FrameDecoder::new(&compressed[..]);
let mut output = String::new();
decoder
.read_to_string(&mut output)
.expect("read should succeed");
assert_eq!(output, "Part 1. Part 2. Part 3.");
}
#[test]
fn test_block_roundtrip_all_same_byte() {
for byte_val in [0x00, 0x55, 0xAA, 0xFF] {
let data = vec![byte_val; 50_000];
let compressed = compress(&data);
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data);
}
}
#[test]
fn test_block_roundtrip_lorem_ipsum() {
let data = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. \
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris \
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in \
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in \
culpa qui officia deserunt mollit anim id est laborum.";
let compressed = compress(data);
assert!(compressed.len() < data.len());
let decompressed = decompress(&compressed).expect("should decompress");
assert_eq!(decompressed, data.as_slice());
}
}