Skip to main content

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}