1#![deny(trivial_casts, trivial_numeric_casts, missing_docs)]
2
3#![cfg_attr(not(feature = "std"), no_std)]
29#![cfg_attr(feature = "nightly", feature(doc_cfg))]
30
31#[cfg(not(feature = "std"))]
33macro_rules! debug {
34 ( $( $_:expr ),* ) => {};
35}
36#[cfg(not(feature = "std"))]
37macro_rules! trace {
38 ( $( $_:expr ),* ) => {};
39}
40#[cfg(not(feature = "std"))]
41macro_rules! log_enabled {
42 ( $( $_:expr ),* ) => {
43 false
44 };
45}
46
47#[cfg_attr(not(feature = "std"), macro_use)]
48extern crate alloc;
49
50pub use deflate::{BlockType, DeflateEncoder};
51#[cfg(feature = "gzip")]
52pub use gzip::GzipEncoder;
53#[cfg(all(test, feature = "std"))]
54use proptest::prelude::*;
55#[cfg(feature = "zlib")]
56pub use zlib::ZlibEncoder;
57
58mod blocksplitter;
59mod cache;
60mod deflate;
61#[cfg(feature = "gzip")]
62mod gzip;
63mod hash;
64#[cfg(any(doc, not(feature = "std")))]
65mod io;
66mod iter;
67mod katajainen;
68mod lz77;
69#[cfg(not(feature = "std"))]
70mod math;
71mod squeeze;
72mod symbols;
73mod tree;
74mod util;
75#[cfg(feature = "zlib")]
76mod zlib;
77
78use core::num::NonZeroU64;
79#[cfg(all(not(doc), feature = "std"))]
80use std::io::{Error, Write};
81
82#[cfg(any(doc, not(feature = "std")))]
83pub use io::{Error, ErrorKind, Write};
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
87#[cfg_attr(all(test, feature = "std"), derive(proptest_derive::Arbitrary))]
88pub struct Options {
89 #[cfg_attr(
96 all(test, feature = "std"),
97 proptest(
98 strategy = "(1..=10u64).prop_map(|iteration_count| NonZeroU64::new(iteration_count).unwrap())"
99 )
100 )]
101 pub iteration_count: NonZeroU64,
102 pub iterations_without_improvement: NonZeroU64,
107 pub maximum_block_splits: u16,
112}
113
114impl Default for Options {
115 fn default() -> Self {
116 Self {
117 iteration_count: NonZeroU64::new(15).unwrap(),
118 iterations_without_improvement: NonZeroU64::new(u64::MAX).unwrap(),
119 maximum_block_splits: 15,
120 }
121 }
122}
123
124#[derive(Debug, Copy, Clone)]
126#[cfg(feature = "std")]
127pub enum Format {
128 #[cfg(feature = "gzip")]
134 Gzip,
135 #[cfg(feature = "zlib")]
141 Zlib,
142 Deflate,
150}
151
152#[cfg(feature = "std")]
155pub fn compress<R: std::io::Read, W: Write>(
156 options: Options,
157 output_format: Format,
158 mut in_data: R,
159 out: W,
160) -> Result<(), Error> {
161 match output_format {
162 #[cfg(feature = "gzip")]
163 Format::Gzip => {
164 let mut gzip_encoder = GzipEncoder::new_buffered(options, BlockType::Dynamic, out)?;
165 std::io::copy(&mut in_data, &mut gzip_encoder)?;
166 gzip_encoder.into_inner()?.finish().map(|_| ())
167 }
168 #[cfg(feature = "zlib")]
169 Format::Zlib => {
170 let mut zlib_encoder = ZlibEncoder::new_buffered(options, BlockType::Dynamic, out)?;
171 std::io::copy(&mut in_data, &mut zlib_encoder)?;
172 zlib_encoder.into_inner()?.finish().map(|_| ())
173 }
174 Format::Deflate => {
175 let mut deflate_encoder =
176 DeflateEncoder::new_buffered(options, BlockType::Dynamic, out);
177 std::io::copy(&mut in_data, &mut deflate_encoder)?;
178 deflate_encoder.into_inner()?.finish().map(|_| ())
179 }
180 }
181}
182
183#[doc(hidden)]
184#[deprecated(
185 since = "0.8.2",
186 note = "Object pools are no longer used. This function is now a no-op and will be removed in version 0.9.0."
187)]
188#[cfg(feature = "std")] pub fn prewarm_object_pools() {}
190
191#[cfg(all(test, feature = "std"))]
192mod test {
193 use std::io;
194
195 use miniz_oxide::inflate;
196 use proptest::proptest;
197
198 use super::*;
199
200 proptest! {
201 #[test]
202 fn deflating_is_reversible(
203 options: Options,
204 btype: BlockType,
205 data in prop::collection::vec(any::<u8>(), 0..64 * 1024)
206 ) {
207 let mut compressed_data = Vec::with_capacity(data.len());
208
209 let mut encoder = DeflateEncoder::new(options, btype, &mut compressed_data);
210 io::copy(&mut &*data, &mut encoder).unwrap();
211 encoder.finish().unwrap();
212
213 let decompressed_data = inflate::decompress_to_vec(&compressed_data).expect("Could not inflate compressed stream");
214 prop_assert_eq!(data, decompressed_data, "Decompressed data should match input data");
215 }
216 }
217}