git_zero_core/zlib.rs
1//! Allocation-free streaming zlib encoding and inflation (RFC 1950/1951).
2//! The encoder uses stored blocks; the decoder also accepts fixed and dynamic
3//! Huffman blocks, with caller-owned history and explicit expansion budgets.
4//! The decoder is implemented from [RFC 1950](https://www.rfc-editor.org/rfc/rfc1950)
5//! and [RFC 1951](https://www.rfc-editor.org/rfc/rfc1951).
6//!
7//! ```
8//! # #[cfg(feature = "read")] {
9//! use git_zero_core::{io::{SliceWriter, Write}, zlib::{Inflater, InflateLimits, InflateStatus, WINDOW_SIZE}};
10//! # fn example() -> git_zero_core::Result<()> {
11//! let mut input: &[u8] = &[120, 156, 203, 72, 205, 201, 201, 7, 0, 6, 44, 2, 21];
12//! let mut window = [0; WINDOW_SIZE];
13//! let limits = InflateLimits { max_output: 5, max_ratio: 16, ratio_slack: 0 };
14//! let mut decoder = Inflater::new(&mut window, limits);
15//! let mut scratch = [0; 2];
16//! let mut storage = [0; 5];
17//! let mut staged = SliceWriter::new(&mut storage);
18//! loop {
19//! let progress = decoder.update(input, &mut scratch, true)?;
20//! staged.write_all(&scratch[..progress.written])?;
21//! input = &input[progress.consumed..];
22//! if progress.status == InflateStatus::Finished { break; }
23//! }
24//! assert_eq!(staged.as_bytes(), b"hello");
25//! assert!(input.is_empty());
26//! # Ok(()) }
27//! # example().unwrap();
28//! # }
29//! ```
30pub(crate) mod adler;
31
32/// zlib compressBound for its default window/memory settings (as used by Git).
33/// Includes wrapper/checksum overhead, with checked arithmetic. This is not a
34/// bound on arbitrarily padded streams or other deflate settings.
35/// https://github.com/madler/zlib/blob/master/compress.c
36pub fn compress_bound(length: u64) -> crate::Result<u64> {
37 length
38 .checked_add(length >> 12)
39 .and_then(|size| size.checked_add(length >> 14))
40 .and_then(|size| size.checked_add(length >> 25))
41 .and_then(|size| size.checked_add(13))
42 .ok_or(crate::Error::LimitExceeded)
43}
44
45#[cfg(feature = "read")]
46mod inflate;
47#[cfg(feature = "read")]
48pub use inflate::{InflateLimits, InflateProgress, InflateStatus, Inflater, WINDOW_SIZE};
49
50#[cfg(feature = "read")]
51mod gzip;
52#[cfg(feature = "read")]
53pub use gzip::decode_gzip;
54
55#[cfg(feature = "write")]
56mod encode;
57#[cfg(feature = "write")]
58mod stored;
59#[cfg(feature = "write")]
60pub use encode::write_parts;
61#[cfg(feature = "write")]
62pub(crate) use encode::write_reader;
63#[cfg(feature = "write")]
64pub use stored::StoredEncoder;