1#[cfg(feature = "async-io")]
46pub mod async_snappy;
47pub mod compress;
48pub mod crc32c;
49pub mod decompress;
50pub mod error;
51pub mod frame;
52#[cfg(feature = "parallel")]
53pub mod frame_parallel;
54pub mod pool;
55
56#[cfg(feature = "async-io")]
59pub use async_snappy::{
60 AsyncSnappyCompressor, AsyncSnappyDecompressor, compress_frame_async, decompress_frame_async,
61};
62pub use compress::compress;
63pub use compress::compress_block_with_dict;
64pub use compress::max_compress_len;
65pub use decompress::decompress;
66pub use decompress::decompress_block_with_dict;
67pub use decompress::get_decompress_len as decompress_len;
68pub use error::SnappyError;
69pub use frame::FrameDecoder;
70pub use frame::FrameEncoder;
71pub use frame::compress_frame_pooled;
72pub use frame::compress_frame_with_dict;
73pub use frame::decompress_frame_with_dict;
74#[cfg(feature = "parallel")]
75pub use frame_parallel::compress_parallel;
76pub use pool::PoolStats;
77pub use pool::SnappyPool;
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use std::io::{Read, Write};
83
84 #[test]
85 fn test_block_roundtrip_empty() {
86 let data: &[u8] = b"";
87 let compressed = compress(data);
88 let decompressed = decompress(&compressed).expect("should decompress");
89 assert_eq!(decompressed, data);
90 }
91
92 #[test]
93 fn test_block_roundtrip_hello() {
94 let data = b"Hello, World!";
95 let compressed = compress(data);
96 let decompressed = decompress(&compressed).expect("should decompress");
97 assert_eq!(decompressed, data);
98 }
99
100 #[test]
101 fn test_block_roundtrip_repeated() {
102 let data = vec![b'A'; 10_000];
103 let compressed = compress(&data);
104 assert!(
106 compressed.len() < data.len() / 2,
107 "compressed {} vs original {}",
108 compressed.len(),
109 data.len()
110 );
111 let decompressed = decompress(&compressed).expect("should decompress");
112 assert_eq!(decompressed, data);
113 }
114
115 #[test]
116 fn test_block_roundtrip_pattern() {
117 let data = b"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
118 let compressed = compress(data);
119 let decompressed = decompress(&compressed).expect("should decompress");
120 assert_eq!(decompressed, data.as_slice());
121 }
122
123 #[test]
124 fn test_block_roundtrip_binary() {
125 let data: Vec<u8> = (0..=255).cycle().take(4096).collect();
126 let compressed = compress(&data);
127 let decompressed = decompress(&compressed).expect("should decompress");
128 assert_eq!(decompressed, data);
129 }
130
131 #[test]
132 fn test_block_roundtrip_single_byte() {
133 let data = [0x42];
134 let compressed = compress(&data);
135 let decompressed = decompress(&compressed).expect("should decompress");
136 assert_eq!(decompressed, data);
137 }
138
139 #[test]
140 fn test_block_roundtrip_two_bytes() {
141 let data = [0x42, 0x43];
142 let compressed = compress(&data);
143 let decompressed = decompress(&compressed).expect("should decompress");
144 assert_eq!(decompressed, data);
145 }
146
147 #[test]
148 fn test_block_roundtrip_three_bytes() {
149 let data = [0x42, 0x43, 0x44];
150 let compressed = compress(&data);
151 let decompressed = decompress(&compressed).expect("should decompress");
152 assert_eq!(decompressed, data);
153 }
154
155 #[test]
156 fn test_decompress_len() {
157 let data = vec![0u8; 12345];
158 let compressed = compress(&data);
159 let len = decompress_len(&compressed).expect("should decode length");
160 assert_eq!(len, 12345);
161 }
162
163 #[test]
164 fn test_max_compress_len_bounds() {
165 for size in [0, 1, 100, 1000, 65536, 1_000_000] {
166 let max_len = max_compress_len(size);
167 let data = vec![0xFFu8; size];
168 let compressed = compress(&data);
169 assert!(
170 compressed.len() <= max_len,
171 "compressed {} > max {} for input size {}",
172 compressed.len(),
173 max_len,
174 size
175 );
176 }
177 }
178
179 #[test]
180 fn test_decompress_invalid_data() {
181 let garbage = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
183 let result = decompress(&garbage);
184 assert!(result.is_err());
185 }
186
187 #[test]
188 fn test_frame_roundtrip_various_sizes() {
189 for size in [0, 1, 10, 100, 1000, 65535, 65536, 65537, 100_000] {
190 let data: Vec<u8> = (0..size).map(|i| (i % 251) as u8).collect();
191
192 let mut compressed = Vec::new();
193 {
194 let mut encoder = FrameEncoder::new(&mut compressed);
195 encoder
196 .write_all(&data)
197 .unwrap_or_else(|e| panic!("write failed for size {size}: {e}"));
198 encoder
199 .finish()
200 .unwrap_or_else(|e| panic!("finish failed for size {size}: {e}"));
201 }
202
203 let mut decoder = FrameDecoder::new(&compressed[..]);
204 let mut output = Vec::new();
205 decoder
206 .read_to_end(&mut output)
207 .unwrap_or_else(|e| panic!("read failed for size {size}: {e}"));
208
209 assert_eq!(output, data, "roundtrip mismatch for size {size}");
210 }
211 }
212
213 #[test]
214 fn test_frame_multi_write_roundtrip() {
215 let mut compressed = Vec::new();
216 {
217 let mut encoder = FrameEncoder::new(&mut compressed);
218 encoder
219 .write_all(b"Part 1. ")
220 .expect("write should succeed");
221 encoder
222 .write_all(b"Part 2. ")
223 .expect("write should succeed");
224 encoder.write_all(b"Part 3.").expect("write should succeed");
225 encoder.finish().expect("finish should succeed");
226 }
227
228 let mut decoder = FrameDecoder::new(&compressed[..]);
229 let mut output = String::new();
230 decoder
231 .read_to_string(&mut output)
232 .expect("read should succeed");
233
234 assert_eq!(output, "Part 1. Part 2. Part 3.");
235 }
236
237 #[test]
238 fn test_block_roundtrip_all_same_byte() {
239 for byte_val in [0x00, 0x55, 0xAA, 0xFF] {
241 let data = vec![byte_val; 50_000];
242 let compressed = compress(&data);
243 let decompressed = decompress(&compressed).expect("should decompress");
244 assert_eq!(decompressed, data);
245 }
246 }
247
248 #[test]
249 fn test_block_roundtrip_lorem_ipsum() {
250 let data = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. \
251 Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
252 Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris \
253 nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in \
254 reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
255 pariatur. Excepteur sint occaecat cupidatat non proident, sunt in \
256 culpa qui officia deserunt mollit anim id est laborum.";
257 let compressed = compress(data);
258 assert!(compressed.len() < data.len());
260 let decompressed = decompress(&compressed).expect("should decompress");
261 assert_eq!(decompressed, data.as_slice());
262 }
263}