#![warn(clippy::too_many_lines, clippy::cognitive_complexity)]
#![deny(unsafe_code)]
mod block;
mod encoder;
mod huffman;
mod lz;
mod parse;
mod tables;
#[cfg(all(test, feature = "alloc"))]
mod tests;
mod write;
#[cfg(feature = "std")]
mod writer;
pub use encoder::{Encoder, Progress};
pub const TABLES_LEN: usize = parse::TABLES_LEN;
pub const MIN_BUFFER_LEN: usize = encoder::MIN_BUF_LEN;
#[cfg(feature = "std")]
pub use writer::Writer;
use crate::Format;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Level(u8);
impl Level {
pub const NONE: Level = Level(0);
pub const FASTEST: Level = Level(1);
pub const DEFAULT: Level = Level(6);
pub const BEST: Level = Level(9);
#[must_use]
pub const fn new(level: u8) -> Self {
assert!(level <= 9, "compression levels go from 0 to 9");
Level(level)
}
#[must_use]
pub const fn get(self) -> u8 {
self.0
}
}
impl Default for Level {
fn default() -> Self {
Level::DEFAULT
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Flush {
None,
Sync,
Full,
Finish,
}
#[must_use]
pub const fn compress_bound(format: Format, len: usize) -> usize {
let blocks = len.div_ceil(block::MIN_BLOCK_LENGTH);
let blocks = if blocks == 0 { 1 } else { blocks };
let wrapper = match format {
Format::Deflate => 0,
Format::Zlib => 2 + 4,
Format::Gzip => 10 + 8,
};
wrapper + 5 * blocks + len
}
#[cfg(feature = "alloc")]
pub(crate) fn compress(format: Format, level: Level, input: &[u8]) -> alloc::vec::Vec<u8> {
let mut e = Encoder::new(format, level);
let mut out = alloc::vec![0; compress_bound(format, input.len())];
let p = e.compress(input, &mut out, Flush::Finish);
assert!(p.done, "the output buffer was smaller than compress_bound");
let len = p.output.len();
out.truncate(len);
out.shrink_to_fit();
out
}