#![deny(trivial_casts, trivial_numeric_casts, missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "nightly", feature(doc_cfg))]
#[cfg(not(feature = "std"))]
macro_rules! debug {
( $( $_:expr ),* ) => {};
}
#[cfg(not(feature = "std"))]
macro_rules! trace {
( $( $_:expr ),* ) => {};
}
#[cfg(not(feature = "std"))]
macro_rules! log_enabled {
( $( $_:expr ),* ) => {
false
};
}
#[cfg_attr(not(feature = "std"), macro_use)]
extern crate alloc;
pub use deflate::{BlockType, DeflateEncoder};
#[cfg(feature = "gzip")]
pub use gzip::GzipEncoder;
#[cfg(all(test, feature = "std"))]
use proptest::prelude::*;
#[cfg(feature = "zlib")]
pub use zlib::ZlibEncoder;
mod blocksplitter;
mod cache;
mod deflate;
#[cfg(feature = "gzip")]
mod gzip;
mod hash;
#[cfg(any(doc, not(feature = "std")))]
mod io;
mod iter;
mod katajainen;
mod lz77;
#[cfg(not(feature = "std"))]
mod math;
mod squeeze;
mod symbols;
mod tree;
mod util;
#[cfg(feature = "zlib")]
mod zlib;
use core::num::NonZeroU64;
#[cfg(all(not(doc), feature = "std"))]
use std::io::{Error, Write};
#[cfg(any(doc, not(feature = "std")))]
pub use io::{Error, ErrorKind, Write};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(all(test, feature = "std"), derive(proptest_derive::Arbitrary))]
pub struct Options {
#[cfg_attr(
all(test, feature = "std"),
proptest(
strategy = "(1..=10u64).prop_map(|iteration_count| NonZeroU64::new(iteration_count).unwrap())"
)
)]
pub iteration_count: NonZeroU64,
pub iterations_without_improvement: NonZeroU64,
pub maximum_block_splits: u16,
}
impl Default for Options {
fn default() -> Self {
Self {
iteration_count: NonZeroU64::new(15).unwrap(),
iterations_without_improvement: NonZeroU64::new(u64::MAX).unwrap(),
maximum_block_splits: 15,
}
}
}
#[derive(Debug, Copy, Clone)]
#[cfg(feature = "std")]
pub enum Format {
#[cfg(feature = "gzip")]
Gzip,
#[cfg(feature = "zlib")]
Zlib,
Deflate,
}
#[cfg(feature = "std")]
pub fn compress<R: std::io::Read, W: Write>(
options: Options,
output_format: Format,
mut in_data: R,
out: W,
) -> Result<(), Error> {
match output_format {
#[cfg(feature = "gzip")]
Format::Gzip => {
let mut gzip_encoder = GzipEncoder::new_buffered(options, BlockType::Dynamic, out)?;
std::io::copy(&mut in_data, &mut gzip_encoder)?;
gzip_encoder.into_inner()?.finish().map(|_| ())
}
#[cfg(feature = "zlib")]
Format::Zlib => {
let mut zlib_encoder = ZlibEncoder::new_buffered(options, BlockType::Dynamic, out)?;
std::io::copy(&mut in_data, &mut zlib_encoder)?;
zlib_encoder.into_inner()?.finish().map(|_| ())
}
Format::Deflate => {
let mut deflate_encoder =
DeflateEncoder::new_buffered(options, BlockType::Dynamic, out);
std::io::copy(&mut in_data, &mut deflate_encoder)?;
deflate_encoder.into_inner()?.finish().map(|_| ())
}
}
}
#[doc(hidden)]
#[deprecated(
since = "0.8.2",
note = "Object pools are no longer used. This function is now a no-op and will be removed in version 0.9.0."
)]
#[cfg(feature = "std")] pub fn prewarm_object_pools() {}
#[cfg(all(test, feature = "std"))]
mod test {
use std::io;
use miniz_oxide::inflate;
use proptest::proptest;
use super::*;
proptest! {
#[test]
fn deflating_is_reversible(
options: Options,
btype: BlockType,
data in prop::collection::vec(any::<u8>(), 0..64 * 1024)
) {
let mut compressed_data = Vec::with_capacity(data.len());
let mut encoder = DeflateEncoder::new(options, btype, &mut compressed_data);
io::copy(&mut &*data, &mut encoder).unwrap();
encoder.finish().unwrap();
let decompressed_data = inflate::decompress_to_vec(&compressed_data).expect("Could not inflate compressed stream");
prop_assert_eq!(data, decompressed_data, "Decompressed data should match input data");
}
}
}