compress_lib/zlib.rs
1//! zlib framing (RFC 1950): a two-byte header, raw DEFLATE, and an Adler-32
2//! of the data.
3//!
4//! This is also HTTP's `deflate` content coding (RFC 9110 section
5//! 8.4.1.2).
6//!
7//! ```
8//! use compress_lib::zlib;
9//!
10//! let packed = zlib::compress(b"hello, hello, hello");
11//! assert_eq!(zlib::decompress(&packed)?, b"hello, hello, hello");
12//! # Ok::<(), compress_lib::Error>(())
13//! ```
14
15use alloc::vec::Vec;
16
17use crate::{
18 Error, ErrorKind, Level, Limits, Progress, Status,
19 checksum::{Adler32, adler32},
20 deflate::{Deflater, Flush, Inflater},
21};
22
23/// Compresses `data` into a complete zlib stream at level 6.
24///
25/// # Examples
26///
27/// ```
28/// let packed = compress_lib::zlib::compress(b"data");
29/// assert_eq!(&packed[..2], &[0x78, 0x9C]);
30/// ```
31#[must_use]
32pub fn compress(data: &[u8]) -> Vec<u8> {
33 compress_with(data, Level::DEFAULT)
34}
35
36/// Compresses `data` into a complete zlib stream at `level`.
37///
38/// # Examples
39///
40/// ```
41/// use compress_lib::{Level, zlib};
42///
43/// let packed = zlib::compress_with(b"data", Level::BEST);
44/// assert_eq!(&packed[..2], &[0x78, 0xDA]);
45/// assert_eq!(zlib::decompress(&packed)?, b"data");
46/// # Ok::<(), compress_lib::Error>(())
47/// ```
48#[must_use]
49pub fn compress_with(data: &[u8], level: Level) -> Vec<u8> {
50 let mut encoder = Encoder::new(level);
51 let mut out = Vec::with_capacity(data.len() / 2 + 64);
52 // Fails only when the vector cannot grow, which aborts first.
53 let _ = encoder.compress_vec(data, &mut out, Flush::Finish);
54 out
55}
56
57/// Decompresses a complete zlib stream with the default [`Limits`].
58///
59/// # Errors
60///
61/// Any decoding error; `ChecksumMismatch` when the Adler-32 differs;
62/// `DictionaryRequired` for streams that need a preset dictionary (use
63/// [`Decoder::set_dictionary`]); `UnexpectedEnd`, `TrailingData`,
64/// `OutputLimit` as for raw DEFLATE.
65///
66/// # Examples
67///
68/// ```
69/// use compress_lib::{ErrorKind, zlib};
70///
71/// let mut packed = zlib::compress(b"data");
72/// let n = packed.len();
73/// packed[n - 1] ^= 1;
74/// assert_eq!(zlib::decompress(&packed).unwrap_err().kind(), ErrorKind::ChecksumMismatch);
75/// ```
76pub fn decompress(data: &[u8]) -> Result<Vec<u8>, Error> {
77 decompress_with(data, Limits::new())
78}
79
80/// Decompresses a complete zlib stream with the given limits.
81///
82/// # Errors
83///
84/// As [`decompress`].
85///
86/// # Examples
87///
88/// ```
89/// use compress_lib::{ErrorKind, Limits, zlib};
90///
91/// let packed = zlib::compress(&[0u8; 10_000]);
92/// let tight = Limits::new().with_max_output(100);
93/// assert_eq!(zlib::decompress_with(&packed, tight).unwrap_err().kind(), ErrorKind::OutputLimit);
94/// ```
95pub fn decompress_with(data: &[u8], limits: Limits) -> Result<Vec<u8>, Error> {
96 let mut decoder = Decoder::one_shot(limits);
97 let mut out = Vec::new();
98 let reserve = data.len().saturating_mul(4).clamp(64, 1 << 20);
99 let cap = usize::try_from(limits.max_output()).unwrap_or(usize::MAX);
100 if out.try_reserve(reserve.min(cap)).is_err() {
101 return Err(Error::config(ErrorKind::AllocationFailed));
102 }
103 let p = decoder.finish_vec(data, &mut out)?;
104 if p.consumed != data.len() {
105 return Err(Error::new(ErrorKind::TrailingData, p.consumed as u64));
106 }
107 Ok(out)
108}
109
110/// Checks a zlib header: compression method 8, window at most 32 KiB,
111/// header check value.
112pub(crate) fn header_ok(cmf: u8, flg: u8) -> bool {
113 cmf & 0x0F == 8 && cmf >> 4 <= 7 && ((u16::from(cmf) << 8) | u16::from(flg)) % 31 == 0
114}
115
116#[derive(Clone, Copy, Debug, PartialEq, Eq)]
117enum State {
118 Header,
119 DictId,
120 Body,
121 Trailer,
122 Done,
123}
124
125/// A streaming zlib decoder.
126///
127/// The same shape as [`Inflater`]; the header is checked as it arrives, and
128/// the Adler-32 trailer is verified before `Done` is returned.
129///
130/// # Examples
131///
132/// ```
133/// use compress_lib::{deflate::Status, zlib};
134///
135/// let packed = zlib::compress(b"streamed");
136/// let mut decoder = zlib::Decoder::new();
137/// let mut out = [0u8; 32];
138/// let p = decoder.finish(&packed, &mut out)?;
139/// assert_eq!(p.status, Status::Done);
140/// assert_eq!(&out[..p.produced], b"streamed");
141/// # Ok::<(), compress_lib::Error>(())
142/// ```
143#[derive(Debug)]
144pub struct Decoder {
145 inflater: Inflater,
146 state: State,
147 /// Header or trailer bytes collected so far.
148 held: [u8; 4],
149 held_len: usize,
150 adler: Adler32,
151 dictionary: Option<Vec<u8>>,
152 dictionary_id: Option<u32>,
153 max_window_bits: u8,
154 consumed_total: u64,
155 failed: Option<Error>,
156}
157
158impl Default for Decoder {
159 fn default() -> Self {
160 Self::new()
161 }
162}
163
164impl Decoder {
165 /// A decoder accepting windows up to 32 KiB, with the default limits.
166 ///
167 /// # Examples
168 ///
169 /// ```
170 /// let decoder = compress_lib::zlib::Decoder::new();
171 /// assert!(!decoder.is_done());
172 /// ```
173 #[must_use]
174 pub fn new() -> Self {
175 Self::from_inflater(Inflater::new(), 15)
176 }
177
178 pub(crate) fn one_shot(limits: Limits) -> Self {
179 Self::from_inflater(Inflater::without_history(limits), 15)
180 }
181
182 fn from_inflater(inflater: Inflater, max_window_bits: u8) -> Self {
183 Self {
184 inflater,
185 state: State::Header,
186 held: [0; 4],
187 held_len: 0,
188 adler: Adler32::new(),
189 dictionary: None,
190 dictionary_id: None,
191 max_window_bits,
192 consumed_total: 0,
193 failed: None,
194 }
195 }
196
197 /// Accepts windows up to `2^bits` bytes (8 to 15); a header naming a
198 /// larger one fails with `InvalidWindowBits`. The decoder's own window
199 /// shrinks with it.
200 ///
201 /// # Errors
202 ///
203 /// [`ErrorKind::InvalidWindowBits`] outside 8 to 15.
204 ///
205 /// # Examples
206 ///
207 /// ```
208 /// use compress_lib::{ErrorKind, Level, zlib};
209 ///
210 /// let packed = zlib::compress(b"data"); // window bits 15
211 /// let mut small = zlib::Decoder::new().with_window_bits(9)?;
212 /// let err = small.finish(&packed, &mut [0u8; 16]).unwrap_err();
213 /// assert_eq!(err.kind(), ErrorKind::InvalidWindowBits);
214 /// # Ok::<(), compress_lib::Error>(())
215 /// ```
216 pub fn with_window_bits(mut self, bits: u8) -> Result<Self, Error> {
217 self.inflater = self.inflater.with_window_bits(bits)?;
218 self.max_window_bits = bits;
219 Ok(self)
220 }
221
222 /// Sets the limits checked while decoding.
223 ///
224 /// # Examples
225 ///
226 /// ```
227 /// use compress_lib::{Limits, zlib};
228 ///
229 /// let decoder = zlib::Decoder::new().with_limits(Limits::new().with_max_output(1 << 20));
230 /// # let _ = decoder;
231 /// ```
232 #[must_use]
233 pub fn with_limits(mut self, limits: Limits) -> Self {
234 self.inflater = self.inflater.with_limits(limits);
235 self
236 }
237
238 /// Gives the preset dictionary for streams that name one (FDICT). It is
239 /// used only when the header asks for it, and only if its Adler-32
240 /// matches the header's dictionary id.
241 ///
242 /// # Errors
243 ///
244 /// [`ErrorKind::InvalidState`] after the body has started.
245 ///
246 /// # Examples
247 ///
248 /// ```
249 /// use compress_lib::{Level, zlib};
250 ///
251 /// let dict = b"common words: hello world";
252 /// let mut enc = zlib::Encoder::new(Level::BEST);
253 /// enc.set_dictionary(dict)?;
254 /// let mut packed = Vec::new();
255 /// enc.compress_vec(b"hello world", &mut packed, compress_lib::deflate::Flush::Finish)?;
256 ///
257 /// let mut dec = zlib::Decoder::new();
258 /// dec.set_dictionary(dict)?;
259 /// let mut out = Vec::new();
260 /// dec.finish_vec(&packed, &mut out)?;
261 /// assert_eq!(out, b"hello world");
262 /// # Ok::<(), compress_lib::Error>(())
263 /// ```
264 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<(), Error> {
265 if !matches!(self.state, State::Header | State::DictId) {
266 return Err(Error::config(ErrorKind::InvalidState));
267 }
268 let mut stored = Vec::new();
269 if stored.try_reserve_exact(dictionary.len()).is_err() {
270 return Err(Error::config(ErrorKind::AllocationFailed));
271 }
272 stored.extend_from_slice(dictionary);
273 self.dictionary = Some(stored);
274 Ok(())
275 }
276
277 /// The dictionary id (Adler-32 of the dictionary) the header names, once
278 /// the header has been read.
279 ///
280 /// # Examples
281 ///
282 /// ```
283 /// use compress_lib::zlib;
284 ///
285 /// let mut dec = zlib::Decoder::new();
286 /// dec.finish(&zlib::compress(b"x"), &mut [0u8; 4])?;
287 /// assert_eq!(dec.dictionary_id(), None);
288 /// # Ok::<(), compress_lib::Error>(())
289 /// ```
290 #[must_use]
291 pub fn dictionary_id(&self) -> Option<u32> {
292 self.dictionary_id
293 }
294
295 /// `true` once the trailer has been verified.
296 ///
297 /// # Examples
298 ///
299 /// ```
300 /// use compress_lib::zlib;
301 ///
302 /// let mut dec = zlib::Decoder::new();
303 /// dec.finish(&zlib::compress(b""), &mut [])?;
304 /// assert!(dec.is_done());
305 /// # Ok::<(), compress_lib::Error>(())
306 /// ```
307 #[must_use]
308 pub fn is_done(&self) -> bool {
309 self.state == State::Done
310 }
311
312 /// Compressed bytes consumed, header and trailer included.
313 ///
314 /// # Examples
315 ///
316 /// ```
317 /// use compress_lib::zlib;
318 ///
319 /// let packed = zlib::compress(b"x");
320 /// let mut dec = zlib::Decoder::new();
321 /// dec.finish(&packed, &mut [0u8; 4])?;
322 /// assert_eq!(dec.total_in(), packed.len() as u64);
323 /// # Ok::<(), compress_lib::Error>(())
324 /// ```
325 #[must_use]
326 pub fn total_in(&self) -> u64 {
327 self.consumed_total
328 }
329
330 /// Decompressed bytes produced.
331 ///
332 /// # Examples
333 ///
334 /// ```
335 /// use compress_lib::zlib;
336 ///
337 /// let mut dec = zlib::Decoder::new();
338 /// dec.finish(&zlib::compress(b"four"), &mut [0u8; 8])?;
339 /// assert_eq!(dec.total_out(), 4);
340 /// # Ok::<(), compress_lib::Error>(())
341 /// ```
342 #[must_use]
343 pub fn total_out(&self) -> u64 {
344 self.inflater.total_out()
345 }
346
347 /// Starts over for a new stream, keeping allocations (and the
348 /// dictionary, if one was given).
349 ///
350 /// # Examples
351 ///
352 /// ```
353 /// use compress_lib::zlib;
354 ///
355 /// let mut dec = zlib::Decoder::new();
356 /// dec.finish(&zlib::compress(b"a"), &mut [0u8; 4])?;
357 /// dec.reset();
358 /// dec.finish(&zlib::compress(b"b"), &mut [0u8; 4])?;
359 /// # Ok::<(), compress_lib::Error>(())
360 /// ```
361 pub fn reset(&mut self) {
362 self.inflater.reset();
363 self.state = State::Header;
364 self.held_len = 0;
365 self.adler = Adler32::new();
366 self.dictionary_id = None;
367 self.consumed_total = 0;
368 self.failed = None;
369 }
370
371 /// Heap bytes held.
372 ///
373 /// # Examples
374 ///
375 /// ```
376 /// assert!(compress_lib::zlib::Decoder::new().memory_in_use() > 32 * 1024);
377 /// ```
378 #[must_use]
379 pub fn memory_in_use(&self) -> usize {
380 self.inflater.memory_in_use() + self.dictionary.as_ref().map_or(0, Vec::capacity)
381 }
382
383 /// Decompresses as much of `input` into `output` as fits; more input may
384 /// follow. As [`Inflater::decompress`], with `Done` only after the
385 /// trailer is verified.
386 ///
387 /// # Errors
388 ///
389 /// Decoding errors, `InvalidHeader`, `InvalidWindowBits`,
390 /// `DictionaryRequired`, `WrongDictionary`, `ChecksumMismatch`, and the
391 /// limits.
392 ///
393 /// # Examples
394 ///
395 /// ```
396 /// use compress_lib::{deflate::Status, zlib};
397 ///
398 /// let packed = zlib::compress(b"split");
399 /// let mut dec = zlib::Decoder::new();
400 /// let mut out = [0u8; 16];
401 /// let a = dec.decompress(&packed[..3], &mut out)?;
402 /// assert_eq!(a.status, Status::NeedsInput);
403 /// let b = dec.decompress(&packed[3..], &mut out[a.produced..])?;
404 /// assert_eq!(b.status, Status::Done);
405 /// # Ok::<(), compress_lib::Error>(())
406 /// ```
407 pub fn decompress(&mut self, input: &[u8], output: &mut [u8]) -> Result<Progress, Error> {
408 self.run(input, Sink::Slice(output), false)
409 }
410
411 /// As [`decompress`](Decoder::decompress), with `input` the last of the
412 /// stream.
413 ///
414 /// # Errors
415 ///
416 /// As `decompress`, plus `UnexpectedEnd`.
417 ///
418 /// # Examples
419 ///
420 /// ```
421 /// use compress_lib::{ErrorKind, zlib};
422 ///
423 /// let packed = zlib::compress(b"data");
424 /// let err = zlib::Decoder::new().finish(&packed[..packed.len() - 1], &mut [0u8; 8]).unwrap_err();
425 /// assert_eq!(err.kind(), ErrorKind::UnexpectedEnd);
426 /// ```
427 pub fn finish(&mut self, input: &[u8], output: &mut [u8]) -> Result<Progress, Error> {
428 self.run(input, Sink::Slice(output), true)
429 }
430
431 /// Decompresses `input`, appending to `out`.
432 ///
433 /// # Errors
434 ///
435 /// As [`decompress`](Decoder::decompress), plus `AllocationFailed`.
436 ///
437 /// # Examples
438 ///
439 /// ```
440 /// use compress_lib::zlib;
441 ///
442 /// let mut out = Vec::new();
443 /// zlib::Decoder::new().decompress_vec(&zlib::compress(b"vec"), &mut out)?;
444 /// assert_eq!(out, b"vec");
445 /// # Ok::<(), compress_lib::Error>(())
446 /// ```
447 pub fn decompress_vec(&mut self, input: &[u8], out: &mut Vec<u8>) -> Result<Progress, Error> {
448 self.run(input, Sink::Vec(out), false)
449 }
450
451 /// As [`decompress_vec`](Decoder::decompress_vec), with `input` the last
452 /// of the stream.
453 ///
454 /// # Errors
455 ///
456 /// As `decompress_vec`, plus `UnexpectedEnd`.
457 ///
458 /// # Examples
459 ///
460 /// ```
461 /// use compress_lib::zlib;
462 ///
463 /// let mut out = Vec::new();
464 /// zlib::Decoder::new().finish_vec(&zlib::compress(b"vec"), &mut out)?;
465 /// assert_eq!(out, b"vec");
466 /// # Ok::<(), compress_lib::Error>(())
467 /// ```
468 pub fn finish_vec(&mut self, input: &[u8], out: &mut Vec<u8>) -> Result<Progress, Error> {
469 self.run(input, Sink::Vec(out), true)
470 }
471
472 fn fail(&mut self, kind: ErrorKind, at: usize) -> Error {
473 let e = Error::new(kind, self.consumed_total + at as u64);
474 self.failed = Some(e);
475 e
476 }
477
478 fn run(&mut self, input: &[u8], mut sink: Sink<'_>, last: bool) -> Result<Progress, Error> {
479 if let Some(e) = self.failed {
480 return Err(e);
481 }
482 let mut ip = 0;
483 let mut produced = 0;
484 let status = loop {
485 match self.state {
486 State::Header | State::DictId | State::Trailer => {
487 let need = if self.state == State::Header { 2 } else { 4 };
488 while self.held_len < need && ip < input.len() {
489 self.held[self.held_len] = input[ip];
490 self.held_len += 1;
491 ip += 1;
492 }
493 if self.held_len < need {
494 break Status::NeedsInput;
495 }
496 self.held_len = 0;
497 if let Err(kind) = self.on_field() {
498 return Err(self.fail(kind, ip));
499 }
500 }
501 State::Body => {
502 let r = match &mut sink {
503 Sink::Slice(out) => self
504 .inflater
505 .decompress(&input[ip..], &mut out[produced..])
506 .inspect(|p| {
507 self.adler.update(&out[produced..produced + p.produced]);
508 }),
509 Sink::Vec(out) => {
510 let at = out.len();
511 self.inflater
512 .decompress_vec(&input[ip..], out)
513 .inspect(|_| {
514 self.adler.update(&out[at..]);
515 })
516 }
517 };
518 let p = match r {
519 Ok(p) => p,
520 Err(e) => {
521 self.failed = Some(e);
522 return Err(e);
523 }
524 };
525 ip += p.consumed;
526 produced += p.produced;
527 match p.status {
528 Status::Done => self.state = State::Trailer,
529 Status::NeedsOutput => break Status::NeedsOutput,
530 _ => break Status::NeedsInput,
531 }
532 }
533 State::Done => break Status::Done,
534 }
535 };
536 self.consumed_total += ip as u64;
537 if status == Status::NeedsInput && last {
538 return Err(self.fail(ErrorKind::UnexpectedEnd, 0));
539 }
540 Ok(Progress::new(ip, produced, status))
541 }
542
543 /// Handles a completed header, dictionary id, or trailer.
544 fn on_field(&mut self) -> Result<(), ErrorKind> {
545 match self.state {
546 State::Header => {
547 let (cmf, flg) = (self.held[0], self.held[1]);
548 if !header_ok(cmf, flg) {
549 return Err(ErrorKind::InvalidHeader);
550 }
551 if (cmf >> 4) + 8 > self.max_window_bits {
552 return Err(ErrorKind::InvalidWindowBits);
553 }
554 self.state = if flg & 0x20 != 0 {
555 State::DictId
556 } else {
557 State::Body
558 };
559 }
560 State::DictId => {
561 let id = u32::from_be_bytes(self.held);
562 self.dictionary_id = Some(id);
563 let Some(dict) = &self.dictionary else {
564 return Err(ErrorKind::DictionaryRequired);
565 };
566 if adler32(dict) != id {
567 return Err(ErrorKind::WrongDictionary);
568 }
569 self.inflater.set_dictionary(dict).map_err(|e| e.kind())?;
570 self.state = State::Body;
571 }
572 State::Trailer => {
573 if u32::from_be_bytes(self.held) != self.adler.finish() {
574 return Err(ErrorKind::ChecksumMismatch);
575 }
576 self.state = State::Done;
577 }
578 State::Body | State::Done => {}
579 }
580 Ok(())
581 }
582}
583
584/// Where decoded bytes go.
585pub(crate) enum Sink<'a> {
586 Slice(&'a mut [u8]),
587 Vec(&'a mut Vec<u8>),
588}
589
590/// A streaming zlib encoder.
591///
592/// # Examples
593///
594/// ```
595/// use compress_lib::{Level, deflate::Flush, zlib};
596///
597/// let mut enc = zlib::Encoder::new(Level::DEFAULT);
598/// let mut packed = Vec::new();
599/// enc.compress_vec(b"part one, ", &mut packed, Flush::None)?;
600/// enc.compress_vec(b"part two", &mut packed, Flush::Finish)?;
601/// assert_eq!(zlib::decompress(&packed)?, b"part one, part two");
602/// # Ok::<(), compress_lib::Error>(())
603/// ```
604#[derive(Debug)]
605pub struct Encoder {
606 deflater: Deflater,
607 adler: Adler32,
608 dictionary_id: Option<u32>,
609 /// Header (then trailer) bytes not yet handed out.
610 pending: [u8; 6],
611 pending_start: usize,
612 pending_len: usize,
613 header_written: bool,
614 trailer_written: bool,
615}
616
617impl Default for Encoder {
618 fn default() -> Self {
619 Self::new(Level::DEFAULT)
620 }
621}
622
623impl Encoder {
624 /// An encoder at `level` with window bits 15.
625 ///
626 /// # Examples
627 ///
628 /// ```
629 /// let enc = compress_lib::zlib::Encoder::new(compress_lib::Level::FAST);
630 /// # let _ = enc;
631 /// ```
632 #[must_use]
633 pub fn new(level: Level) -> Self {
634 Self {
635 deflater: Deflater::new(level),
636 adler: Adler32::new(),
637 dictionary_id: None,
638 pending: [0; 6],
639 pending_start: 0,
640 pending_len: 0,
641 header_written: false,
642 trailer_written: false,
643 }
644 }
645
646 /// Sets the window to `2^bits` bytes, 8 to 15 (the header names it;
647 /// zlib's own encoder rounds 8 up to 9, this one does not).
648 ///
649 /// # Errors
650 ///
651 /// [`ErrorKind::InvalidWindowBits`] outside 8 to 15.
652 ///
653 /// # Examples
654 ///
655 /// ```
656 /// use compress_lib::{Level, deflate::Flush, zlib};
657 ///
658 /// let mut enc = zlib::Encoder::new(Level::DEFAULT).with_window_bits(10)?;
659 /// let mut packed = Vec::new();
660 /// enc.compress_vec(b"x", &mut packed, Flush::Finish)?;
661 /// assert_eq!(packed[0], 0x28);
662 /// # Ok::<(), compress_lib::Error>(())
663 /// ```
664 pub fn with_window_bits(mut self, bits: u8) -> Result<Self, Error> {
665 self.deflater = self.deflater.with_window_bits(bits)?;
666 Ok(self)
667 }
668
669 /// Presets a dictionary; the header then names it (FDICT) and the
670 /// decoder must be given the same one. Only before any input.
671 ///
672 /// # Errors
673 ///
674 /// [`ErrorKind::InvalidState`] after input has been given.
675 ///
676 /// # Examples
677 ///
678 /// ```
679 /// let mut enc = compress_lib::zlib::Encoder::default();
680 /// enc.set_dictionary(b"dictionary")?;
681 /// # Ok::<(), compress_lib::Error>(())
682 /// ```
683 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<(), Error> {
684 if self.header_written {
685 return Err(Error::config(ErrorKind::InvalidState));
686 }
687 self.deflater.set_dictionary(dictionary)?;
688 self.dictionary_id = Some(adler32(dictionary));
689 Ok(())
690 }
691
692 /// Starts a new stream, keeping allocations (and no dictionary).
693 ///
694 /// # Examples
695 ///
696 /// ```
697 /// let mut enc = compress_lib::zlib::Encoder::default();
698 /// enc.reset();
699 /// ```
700 pub fn reset(&mut self) {
701 self.deflater.reset();
702 self.adler = Adler32::new();
703 self.dictionary_id = None;
704 self.pending_start = 0;
705 self.pending_len = 0;
706 self.header_written = false;
707 self.trailer_written = false;
708 }
709
710 /// Uncompressed bytes taken.
711 ///
712 /// # Examples
713 ///
714 /// ```
715 /// use compress_lib::{deflate::Flush, zlib};
716 ///
717 /// let mut enc = zlib::Encoder::default();
718 /// enc.compress_vec(b"abc", &mut Vec::new(), Flush::Finish)?;
719 /// assert_eq!(enc.total_in(), 3);
720 /// # Ok::<(), compress_lib::Error>(())
721 /// ```
722 #[must_use]
723 pub fn total_in(&self) -> u64 {
724 self.deflater.total_in()
725 }
726
727 /// Heap bytes held.
728 ///
729 /// # Examples
730 ///
731 /// ```
732 /// assert!(compress_lib::zlib::Encoder::default().memory_in_use() > 0);
733 /// ```
734 #[must_use]
735 pub fn memory_in_use(&self) -> usize {
736 self.deflater.memory_in_use()
737 }
738
739 fn header(&self) -> [u8; 2] {
740 let cmf = ((self.deflater.window_bits() - 8) << 4) | 8;
741 let level_bits = match self.deflater.level().get() {
742 0 | 1 => 0,
743 2..=5 => 1,
744 6 => 2,
745 _ => 3,
746 };
747 let mut flg = (level_bits << 6)
748 | if self.dictionary_id.is_some() {
749 0x20
750 } else {
751 0
752 };
753 let rem = ((u16::from(cmf) << 8) | u16::from(flg)) % 31;
754 if rem != 0 {
755 flg += (31 - rem) as u8;
756 }
757 [cmf, flg]
758 }
759
760 fn drain(&mut self, output: &mut [u8], produced: &mut usize) {
761 let n = self.pending_len.min(output.len() - *produced);
762 output[*produced..*produced + n]
763 .copy_from_slice(&self.pending[self.pending_start..self.pending_start + n]);
764 self.pending_start += n;
765 self.pending_len -= n;
766 *produced += n;
767 }
768
769 /// As [`Deflater::compress`], with the header written first and the
770 /// Adler-32 trailer after `Finish`.
771 ///
772 /// # Errors
773 ///
774 /// As `Deflater::compress`.
775 ///
776 /// # Examples
777 ///
778 /// ```
779 /// use compress_lib::{deflate::{Flush, Status}, zlib};
780 ///
781 /// let mut enc = zlib::Encoder::default();
782 /// let mut out = [0u8; 64];
783 /// let p = enc.compress(b"abc", &mut out, Flush::Finish)?;
784 /// assert_eq!(p.status, Status::Done);
785 /// assert_eq!(zlib::decompress(&out[..p.produced])?, b"abc");
786 /// # Ok::<(), compress_lib::Error>(())
787 /// ```
788 pub fn compress(
789 &mut self,
790 input: &[u8],
791 output: &mut [u8],
792 flush: Flush,
793 ) -> Result<Progress, Error> {
794 let mut produced = 0;
795 if !self.header_written {
796 let h = self.header();
797 self.pending[..2].copy_from_slice(&h);
798 if let Some(id) = self.dictionary_id {
799 self.pending[2..6].copy_from_slice(&id.to_be_bytes());
800 self.pending_len = 6;
801 } else {
802 self.pending_len = 2;
803 }
804 self.pending_start = 0;
805 self.header_written = true;
806 }
807 self.drain(output, &mut produced);
808 if self.pending_len > 0 {
809 return Ok(Progress::new(0, produced, Status::NeedsOutput));
810 }
811 if self.trailer_written {
812 if !input.is_empty() {
813 return Err(Error::config(ErrorKind::InvalidState));
814 }
815 return Ok(Progress::new(0, produced, Status::Done));
816 }
817 let p = self
818 .deflater
819 .compress(input, &mut output[produced..], flush)?;
820 self.adler.update(&input[..p.consumed]);
821 produced += p.produced;
822 if p.status == Status::Done && flush == Flush::Finish {
823 self.pending[..4].copy_from_slice(&self.adler.finish().to_be_bytes());
824 self.pending_start = 0;
825 self.pending_len = 4;
826 self.trailer_written = true;
827 self.drain(output, &mut produced);
828 let status = if self.pending_len == 0 {
829 Status::Done
830 } else {
831 Status::NeedsOutput
832 };
833 return Ok(Progress::new(p.consumed, produced, status));
834 }
835 Ok(Progress::new(p.consumed, produced, p.status))
836 }
837
838 /// As [`compress`](Encoder::compress), appending to `out` until the
839 /// flush point is written.
840 ///
841 /// # Errors
842 ///
843 /// As `compress`, plus `AllocationFailed`.
844 ///
845 /// # Examples
846 ///
847 /// ```
848 /// use compress_lib::{deflate::Flush, zlib};
849 ///
850 /// let mut out = Vec::new();
851 /// zlib::Encoder::default().compress_vec(b"abc", &mut out, Flush::Finish)?;
852 /// assert_eq!(zlib::decompress(&out)?, b"abc");
853 /// # Ok::<(), compress_lib::Error>(())
854 /// ```
855 pub fn compress_vec(
856 &mut self,
857 input: &[u8],
858 out: &mut Vec<u8>,
859 flush: Flush,
860 ) -> Result<Progress, Error> {
861 let start = out.len();
862 let mut consumed = 0;
863 loop {
864 let have = out.len();
865 let room = (input.len() - consumed) / 2 + 1024;
866 if out.capacity() - have < room && out.try_reserve(room).is_err() {
867 return Err(Error::config(ErrorKind::AllocationFailed));
868 }
869 let spare = out.capacity() - have;
870 out.resize(have + spare, 0);
871 match self.compress(&input[consumed..], &mut out[have..], flush) {
872 Ok(p) => {
873 out.truncate(have + p.produced);
874 consumed += p.consumed;
875 if p.status != Status::NeedsOutput {
876 return Ok(Progress::new(consumed, out.len() - start, p.status));
877 }
878 }
879 Err(e) => {
880 out.truncate(have);
881 return Err(e);
882 }
883 }
884 }
885 }
886}
887
888#[cfg(test)]
889mod tests {
890 use alloc::vec;
891
892 use super::*;
893
894 #[test]
895 fn test_zlib_header_values_match_zlib() {
896 assert_eq!(&compress_with(b"", Level::NONE)[..2], &[0x78, 0x01]);
897 assert_eq!(&compress_with(b"", Level::FAST)[..2], &[0x78, 0x01]);
898 assert_eq!(
899 &compress_with(b"", Level::new(4).unwrap())[..2],
900 &[0x78, 0x5E]
901 );
902 assert_eq!(&compress(b"")[..2], &[0x78, 0x9C]);
903 assert_eq!(&compress_with(b"", Level::BEST)[..2], &[0x78, 0xDA]);
904 }
905
906 #[test]
907 fn test_zlib_known_stream_from_python_zlib() {
908 // zlib.compress(b"hello") from CPython's zlib 1.3.
909 let packed = [
910 0x78, 0x9C, 0xCB, 0x48, 0xCD, 0xC9, 0xC9, 0x07, 0x00, 0x06, 0x2C, 0x02, 0x15,
911 ];
912 assert_eq!(decompress(&packed).unwrap(), b"hello");
913 }
914
915 #[test]
916 fn test_zlib_bad_headers_rejected() {
917 // Method 7, window 64 KiB (CINFO 8), bad check value.
918 assert_eq!(
919 decompress(&[0x77, 0x01, 0x03, 0x00]).unwrap_err().kind(),
920 ErrorKind::InvalidHeader
921 );
922 assert_eq!(
923 decompress(&[0x88, 0x1C, 0x03, 0x00]).unwrap_err().kind(),
924 ErrorKind::InvalidHeader
925 );
926 assert_eq!(
927 decompress(&[0x78, 0x9D, 0x03, 0x00]).unwrap_err().kind(),
928 ErrorKind::InvalidHeader
929 );
930 }
931
932 #[test]
933 fn test_zlib_dictionary_required_and_wrong() {
934 let mut enc = Encoder::new(Level::BEST);
935 enc.set_dictionary(b"the dictionary").unwrap();
936 let mut packed = Vec::new();
937 enc.compress_vec(b"the dictionary again", &mut packed, Flush::Finish)
938 .unwrap();
939 assert_eq!(
940 decompress(&packed).unwrap_err().kind(),
941 ErrorKind::DictionaryRequired
942 );
943 let mut dec = Decoder::new();
944 dec.set_dictionary(b"another one").unwrap();
945 assert_eq!(
946 dec.finish_vec(&packed, &mut Vec::new()).unwrap_err().kind(),
947 ErrorKind::WrongDictionary
948 );
949 let mut dec = Decoder::new();
950 dec.set_dictionary(b"the dictionary").unwrap();
951 let mut out = Vec::new();
952 dec.finish_vec(&packed, &mut out).unwrap();
953 assert_eq!(out, b"the dictionary again");
954 assert_eq!(dec.dictionary_id(), Some(adler32(b"the dictionary")));
955 }
956
957 #[test]
958 fn test_zlib_every_split_and_buffer() {
959 let data: Vec<u8> = (0..3000u32).map(|i| (i % 97) as u8).collect();
960 let packed = compress(&data);
961 for step in [1usize, 2, 5, 13] {
962 for out_size in [1usize, 3, 64] {
963 let mut dec = Decoder::new();
964 let mut out = Vec::new();
965 let mut buf = vec![0u8; out_size];
966 let mut pos = 0;
967 loop {
968 let end = (pos + step).min(packed.len());
969 let p = if end == packed.len() {
970 dec.finish(&packed[pos..end], &mut buf).unwrap()
971 } else {
972 dec.decompress(&packed[pos..end], &mut buf).unwrap()
973 };
974 out.extend_from_slice(&buf[..p.produced]);
975 pos += p.consumed;
976 if p.status == Status::Done {
977 break;
978 }
979 }
980 assert_eq!(out, data, "{step}/{out_size}");
981 }
982 }
983 }
984
985 #[test]
986 fn test_zlib_trailer_and_truncation() {
987 let packed = compress(b"checked");
988 for n in 0..packed.len() {
989 assert_eq!(
990 decompress(&packed[..n]).unwrap_err().kind(),
991 ErrorKind::UnexpectedEnd,
992 "prefix {n}"
993 );
994 }
995 let mut extra = packed.clone();
996 extra.push(0);
997 assert_eq!(
998 decompress(&extra).unwrap_err().kind(),
999 ErrorKind::TrailingData
1000 );
1001 let mut bad = packed;
1002 let n = bad.len();
1003 bad[n - 2] ^= 0x10;
1004 assert_eq!(
1005 decompress(&bad).unwrap_err().kind(),
1006 ErrorKind::ChecksumMismatch
1007 );
1008 }
1009}