Skip to main content

compress_lib/deflate/
encoder.rs

1//! The raw DEFLATE (RFC 1951) encoder.
2//!
3//! Input is copied into a sliding window; a hash of three bytes indexes
4//! chains of earlier positions; greedy (levels 1 to 3) or lazy (4 to 9)
5//! matching turns the window into literal and match symbols; every 16,384
6//! symbols (fewer for small windows) a block is written as stored, fixed, or
7//! dynamic Huffman, whichever is smallest. Output waits in a pending buffer
8//! of at most one block until the caller drains it.
9
10use alloc::{vec, vec::Vec};
11
12use super::huffman;
13use crate::{Error, ErrorKind, Level, Progress, Status};
14
15const MIN_MATCH: usize = 3;
16const MAX_MATCH: usize = 258;
17/// Lookahead kept before matching at a position, so a full match and the
18/// hash of the next position always fit.
19const MIN_LOOKAHEAD: usize = MAX_MATCH + MIN_MATCH + 1;
20/// A match of length 3 further back than this costs more than three
21/// literals (zlib's TOO_FAR).
22const TOO_FAR: usize = 4096;
23/// Bytes past the window's logical end, so four-byte loads at any position
24/// of the window are in bounds.
25const WIN_PAD: usize = 8;
26/// Level 0 writes a stored block once this much input is waiting (or half
27/// the buffer, for small windows).
28const STORED_CHUNK: usize = 16 * 1024;
29
30const LENGTH_BASE: [u16; 29] = [
31    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131,
32    163, 195, 227, 258,
33];
34const LENGTH_EXTRA: [u8; 29] = [
35    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
36];
37const DIST_BASE: [u16; 30] = [
38    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
39    2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577,
40];
41const DIST_EXTRA: [u8; 30] = [
42    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
43    13,
44];
45const PRECODE_ORDER: [usize; 19] = [
46    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
47];
48
49/// `LENGTH_CODE[len - 3]`: the length symbol index (0 to 28).
50static LENGTH_CODE: [u8; 256] = {
51    let mut t = [0u8; 256];
52    let mut code = 0;
53    while code < 28 {
54        let mut i = 0;
55        while i < (1 << LENGTH_EXTRA[code]) {
56            t[LENGTH_BASE[code] as usize - 3 + i] = code as u8;
57            i += 1;
58        }
59        code += 1;
60    }
61    // 258 has its own symbol; 257 - 3 = 254 stays in code 27.
62    t[255] = 28;
63    t
64};
65
66/// Distance symbol for `dist - 1` below 256, and for `256 + ((dist - 1) >> 7)`
67/// above (zlib's two-part table).
68static DIST_CODE: [u8; 512] = {
69    let mut t = [0u8; 512];
70    let mut code = 0;
71    while code < 30 {
72        let base = DIST_BASE[code] as usize - 1;
73        let count = 1usize << DIST_EXTRA[code];
74        let mut i = 0;
75        while i < count {
76            let d = base + i;
77            if d < 256 {
78                t[d] = code as u8;
79            } else {
80                t[256 + (d >> 7)] = code as u8;
81            }
82            i += 1;
83        }
84        code += 1;
85    }
86    t
87};
88
89#[inline]
90fn dist_code(dist: usize) -> usize {
91    let d = dist - 1;
92    if d < 256 {
93        DIST_CODE[d] as usize
94    } else {
95        DIST_CODE[256 + (d >> 7)] as usize
96    }
97}
98
99/// Fixed literal/length code lengths.
100const fn fixed_lit_lens() -> [u8; 288] {
101    let mut l = [0u8; 288];
102    let mut i = 0;
103    while i < 288 {
104        l[i] = if i < 144 {
105            8
106        } else if i < 256 {
107            9
108        } else if i < 280 {
109            7
110        } else {
111            8
112        };
113        i += 1;
114    }
115    l
116}
117static FIXED_LIT_LENS: [u8; 288] = fixed_lit_lens();
118
119/// Match-finder settings per level (zlib's configuration table).
120#[derive(Clone, Copy)]
121struct Params {
122    /// Shorten the chain search once a match this long is found.
123    good: usize,
124    /// Greedy levels: insert hashes inside matches up to this length. Lazy
125    /// levels: do not look for a better match once one this long is found.
126    lazy: usize,
127    /// Stop searching at a match this long.
128    nice: usize,
129    /// Chain positions searched per match.
130    chain: usize,
131    lazy_matching: bool,
132}
133
134const fn params(level: u8) -> Params {
135    let (good, lazy, nice, chain, lazy_matching) = match level {
136        1 => (4, 4, 8, 1, false),
137        2 => (4, 5, 16, 8, false),
138        3 => (4, 6, 32, 32, false),
139        4 => (4, 4, 16, 16, true),
140        5 => (8, 16, 32, 32, true),
141        6 => (8, 16, 128, 128, true),
142        7 => (8, 32, 128, 256, true),
143        8 => (32, 128, 258, 1024, true),
144        9 => (32, 258, 258, 4096, true),
145        _ => (0, 0, 0, 0, false),
146    };
147    Params {
148        good,
149        lazy,
150        nice,
151        chain,
152        lazy_matching,
153    }
154}
155
156/// How far a call should go before returning.
157#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
158#[non_exhaustive]
159pub enum Flush {
160    /// Compress as input allows; output may lag behind input.
161    None,
162    /// Write out everything so far, end on a byte boundary with an empty
163    /// stored block (`00 00 FF FF`). History is kept. WebSocket
164    /// permessage-deflate ends every message this way.
165    Sync,
166    /// As `Sync`, and forget history: later data never refers back across
167    /// this point, so a decoder can start here.
168    Full,
169    /// Write out everything and end the stream with a final block.
170    Finish,
171}
172
173/// Memory settings for a [`Deflater`]: the hash table and the symbol
174/// buffer, the two largest parts after the window.
175///
176/// | Setting | Default | Memory | Effect |
177/// |---|---|---|---|
178/// | hash bits | window bits + 1, 9 to 15 (12 at most at level 1) | 2 bytes per entry | fewer bits: less memory, more collisions, slightly larger output |
179/// | block symbols | 2^(window bits + 1), 1,024 to 16,384 | 4 bytes per symbol, plus up to 4 bytes of pending output | fewer: less memory, more block headers |
180///
181/// # Examples
182///
183/// ```
184/// use compress_lib::deflate::MemoryConfig;
185///
186/// let config = MemoryConfig::new().with_hash_bits(11).with_block_symbols(4096);
187/// assert_eq!((config.hash_bits(), config.block_symbols()), (11, 4096));
188/// ```
189#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
190#[non_exhaustive]
191pub struct MemoryConfig {
192    /// 0: chosen from the window bits.
193    hash_bits: u8,
194    /// 0: chosen from the window bits.
195    block_symbols: usize,
196}
197
198impl MemoryConfig {
199    /// Both sizes chosen from the window bits.
200    ///
201    /// # Examples
202    ///
203    /// ```
204    /// assert_eq!(compress_lib::deflate::MemoryConfig::new().hash_bits(), 0);
205    /// ```
206    #[must_use]
207    pub const fn new() -> Self {
208        Self {
209            hash_bits: 0,
210            block_symbols: 0,
211        }
212    }
213
214    /// Sets the hash table to `2^bits` entries; clamped to 8 to 16 (0 keeps
215    /// the default).
216    ///
217    /// # Examples
218    ///
219    /// ```
220    /// assert_eq!(compress_lib::deflate::MemoryConfig::new().with_hash_bits(20).hash_bits(), 16);
221    /// ```
222    #[must_use]
223    pub const fn with_hash_bits(mut self, bits: u8) -> Self {
224        self.hash_bits = if bits == 0 {
225            0
226        } else if bits < 8 {
227            8
228        } else if bits > 16 {
229            16
230        } else {
231            bits
232        };
233        self
234    }
235
236    /// Sets the symbols per block; clamped to 256 to 65,536 (0 keeps the
237    /// default).
238    ///
239    /// # Examples
240    ///
241    /// ```
242    /// assert_eq!(compress_lib::deflate::MemoryConfig::new().with_block_symbols(100).block_symbols(), 256);
243    /// ```
244    #[must_use]
245    pub const fn with_block_symbols(mut self, symbols: usize) -> Self {
246        self.block_symbols = if symbols == 0 {
247            0
248        } else if symbols < 256 {
249            256
250        } else if symbols > 65_536 {
251            65_536
252        } else {
253            symbols
254        };
255        self
256    }
257
258    /// The hash bits set (0: chosen from the window bits).
259    ///
260    /// # Examples
261    ///
262    /// ```
263    /// assert_eq!(compress_lib::deflate::MemoryConfig::new().with_hash_bits(10).hash_bits(), 10);
264    /// ```
265    #[must_use]
266    pub const fn hash_bits(&self) -> u8 {
267        self.hash_bits
268    }
269
270    /// The symbols per block set (0: chosen from the window bits).
271    ///
272    /// # Examples
273    ///
274    /// ```
275    /// assert_eq!(compress_lib::deflate::MemoryConfig::new().block_symbols(), 0);
276    /// ```
277    #[must_use]
278    pub const fn block_symbols(&self) -> usize {
279        self.block_symbols
280    }
281}
282
283/// Scratch for building one block's codes (about 3 KiB, boxed once).
284struct BlockScratch {
285    lit_freq: [u32; 286],
286    dist_freq: [u32; 30],
287    lit_lens: [u8; 286],
288    dist_lens: [u8; 30],
289    lit_codes: [u16; 288],
290    dist_codes: [u16; 30],
291    /// Run-length coded code lengths: (symbol, extra value).
292    rle: [(u8, u8); 316],
293    rle_len: usize,
294    pre_freq: [u32; 19],
295    pre_lens: [u8; 19],
296    pre_codes: [u16; 19],
297}
298
299impl BlockScratch {
300    fn new() -> Self {
301        Self {
302            lit_freq: [0; 286],
303            dist_freq: [0; 30],
304            lit_lens: [0; 286],
305            dist_lens: [0; 30],
306            lit_codes: [0; 288],
307            dist_codes: [0; 30],
308            rle: [(0, 0); 316],
309            rle_len: 0,
310            pre_freq: [0; 19],
311            pre_lens: [0; 19],
312            pre_codes: [0; 19],
313        }
314    }
315}
316
317/// A streaming raw DEFLATE encoder (RFC 1951).
318///
319/// Push input, pull output, with a [`Flush`] choosing how far each call
320/// goes. Memory is fixed when the deflater is built (section 5.6 of the
321/// plan): at window bits 15 and level 6, a 64 KiB window, 128 KiB of hash
322/// chains, 64 KiB of symbols, and up to one block of pending output.
323///
324/// # Examples
325///
326/// ```
327/// use compress_lib::{Level, deflate::{self, Deflater, Flush}};
328///
329/// let mut deflater = Deflater::new(Level::DEFAULT);
330/// let mut packed = Vec::new();
331/// deflater.compress_vec(b"hello, hello, hello", &mut packed, Flush::Finish)?;
332/// assert_eq!(deflate::decompress(&packed)?, b"hello, hello, hello");
333/// # Ok::<(), compress_lib::Error>(())
334/// ```
335pub struct Deflater {
336    memory: MemoryConfig,
337    level: u8,
338    params: Params,
339    window_bits: u8,
340    /// Window buffer of `wsize * span` bytes; positions are indices into it.
341    win: Vec<u8>,
342    /// Logical size of `win`; the vector has `WIN_PAD` more zero bytes so
343    /// four-byte loads near the end stay in bounds.
344    size: usize,
345    wsize: usize,
346    /// History always kept before `strstart`, and so the longest distance
347    /// used: the whole window, or 262 bytes less when the buffer is only two
348    /// windows (zlib's MAX_DIST), so positions fit in 16 bits.
349    keep: usize,
350    strstart: usize,
351    lookahead: usize,
352    /// Start of the current block's input in `win` (negative once slid out).
353    block_start: isize,
354    hash_bits: u32,
355    head: Vec<u16>,
356    prev: Vec<u16>,
357    match_available: bool,
358    match_length: usize,
359    match_start: usize,
360    prev_length: usize,
361    prev_match: usize,
362    /// Symbols of the current block: `dist << 16 | litlen`, where a literal
363    /// has `dist == 0` and a match stores `length - 3`.
364    syms: Vec<u32>,
365    sym_cap: usize,
366    scratch: alloc::boxed::Box<BlockScratch>,
367    pending: Vec<u8>,
368    pending_pos: usize,
369    bitbuf: u64,
370    bitcnt: u32,
371    total_in: u64,
372    total_out: u64,
373    /// The flush asked for has been written into `pending`.
374    flush_written: bool,
375    finished: bool,
376}
377
378impl core::fmt::Debug for Deflater {
379    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
380        f.debug_struct("Deflater")
381            .field("level", &self.level)
382            .field("window_bits", &self.window_bits)
383            .field("total_in", &self.total_in)
384            .field("total_out", &self.total_out)
385            .field("finished", &self.finished)
386            .finish_non_exhaustive()
387    }
388}
389
390impl Default for Deflater {
391    fn default() -> Self {
392        Self::new(Level::DEFAULT)
393    }
394}
395
396impl Deflater {
397    /// A deflater at `level` with window bits 15.
398    ///
399    /// # Examples
400    ///
401    /// ```
402    /// use compress_lib::{Level, deflate::Deflater};
403    ///
404    /// let deflater = Deflater::new(Level::FAST);
405    /// assert_eq!(deflater.level(), Level::FAST);
406    /// ```
407    #[must_use]
408    pub fn new(level: Level) -> Self {
409        Self::build(level.get(), 15, MemoryConfig::new())
410    }
411
412    fn build(level: u8, window_bits: u8, memory: MemoryConfig) -> Self {
413        let wsize = 1usize << window_bits;
414        // At least 8 KiB of buffer, so small windows still read input in
415        // useful pieces; always a whole number of windows (the hash chains
416        // are indexed modulo the window).
417        let span = (8192 / wsize).max(2);
418        // Level 1 probes once, so a table that stays in the first-level cache
419        // is faster and loses little (D-040).
420        let max_hash = if level == 1 { 12 } else { 15 };
421        let hash_bits = match memory.hash_bits {
422            0 => u32::from(window_bits + 1).clamp(9, max_hash),
423            bits => u32::from(bits),
424        };
425        let sym_cap = match memory.block_symbols {
426            0 => (1usize << (window_bits + 1)).clamp(1024, 16_384),
427            n => n,
428        };
429        Self {
430            memory,
431            level,
432            params: params(level),
433            window_bits,
434            win: vec![0; wsize * span + WIN_PAD],
435            size: wsize * span,
436            wsize,
437            keep: if span >= 3 {
438                wsize
439            } else {
440                wsize - MIN_LOOKAHEAD
441            },
442            // Position 0 means "none" in the hash chains, so data starts at 1.
443            strstart: 1,
444            lookahead: 0,
445            block_start: 1,
446            hash_bits,
447            head: vec![0; 1 << hash_bits],
448            prev: vec![0; wsize],
449            match_available: false,
450            match_length: MIN_MATCH - 1,
451            match_start: 0,
452            prev_length: MIN_MATCH - 1,
453            prev_match: 0,
454            syms: Vec::with_capacity(sym_cap),
455            sym_cap,
456            scratch: alloc::boxed::Box::new(BlockScratch::new()),
457            // One block is at most about four bytes per symbol (fixed codes,
458            // longest extra bits), or the stored form of its input.
459            pending: Vec::with_capacity(sym_cap * 4 + wsize * span + 64),
460            pending_pos: 0,
461            bitbuf: 0,
462            bitcnt: 0,
463            total_in: 0,
464            total_out: 0,
465            flush_written: false,
466            finished: false,
467        }
468    }
469
470    /// Sets the window to `2^bits` bytes, 8 to 15: no match distance is ever
471    /// longer (RFC 7692 negotiates these sizes; 8 is a real 256-byte
472    /// window). Smaller windows also use smaller hash and symbol tables.
473    ///
474    /// # Errors
475    ///
476    /// [`ErrorKind::InvalidWindowBits`] outside 8 to 15.
477    ///
478    /// # Examples
479    ///
480    /// ```
481    /// use compress_lib::{Level, deflate::Deflater};
482    ///
483    /// let small = Deflater::new(Level::FAST).with_window_bits(9)?;
484    /// assert!(small.memory_in_use() < Deflater::new(Level::FAST).memory_in_use());
485    /// assert!(Deflater::new(Level::FAST).with_window_bits(7).is_err());
486    /// # Ok::<(), compress_lib::Error>(())
487    /// ```
488    pub fn with_window_bits(self, bits: u8) -> Result<Self, Error> {
489        if !(8..=15).contains(&bits) {
490            return Err(Error::config(ErrorKind::InvalidWindowBits));
491        }
492        Ok(Self::build(self.level, bits, self.memory))
493    }
494
495    /// Sizes the hash table and the symbol buffer explicitly (see
496    /// [`MemoryConfig`]), for many connections on little memory or for a
497    /// little more ratio.
498    ///
499    /// # Examples
500    ///
501    /// ```
502    /// use compress_lib::{Level, deflate::{self, Deflater, Flush, MemoryConfig}};
503    ///
504    /// let lean = MemoryConfig::new().with_hash_bits(9).with_block_symbols(512);
505    /// let mut d = Deflater::new(Level::FAST).with_window_bits(9)?.with_memory(lean);
506    /// assert!(d.memory_in_use() < Deflater::new(Level::FAST).with_window_bits(9)?.memory_in_use());
507    /// let mut out = Vec::new();
508    /// d.compress_vec(b"small and lean", &mut out, Flush::Finish)?;
509    /// assert_eq!(deflate::decompress(&out)?, b"small and lean");
510    /// # Ok::<(), compress_lib::Error>(())
511    /// ```
512    #[must_use]
513    pub fn with_memory(self, memory: MemoryConfig) -> Self {
514        Self::build(self.level, self.window_bits, memory)
515    }
516
517    /// The level in force.
518    ///
519    /// # Examples
520    ///
521    /// ```
522    /// use compress_lib::{Level, deflate::Deflater};
523    ///
524    /// assert_eq!(Deflater::default().level(), Level::DEFAULT);
525    /// ```
526    #[must_use]
527    pub fn level(&self) -> Level {
528        Level::new(self.level).unwrap_or(Level::DEFAULT)
529    }
530
531    /// The window size in bits.
532    ///
533    /// # Examples
534    ///
535    /// ```
536    /// assert_eq!(compress_lib::deflate::Deflater::default().window_bits(), 15);
537    /// ```
538    #[must_use]
539    pub fn window_bits(&self) -> u8 {
540        self.window_bits
541    }
542
543    /// Changes the level for data not yet compressed. The current block is
544    /// ended first when the change switches to or from level 0.
545    ///
546    /// # Examples
547    ///
548    /// ```
549    /// use compress_lib::{Level, deflate::{self, Deflater, Flush}};
550    ///
551    /// let mut deflater = Deflater::new(Level::BEST);
552    /// let mut out = Vec::new();
553    /// deflater.compress_vec(b"header ", &mut out, Flush::None)?;
554    /// deflater.set_level(Level::NONE);
555    /// deflater.compress_vec(b"body", &mut out, Flush::Finish)?;
556    /// assert_eq!(deflate::decompress(&out)?, b"header body");
557    /// # Ok::<(), compress_lib::Error>(())
558    /// ```
559    pub fn set_level(&mut self, level: Level) {
560        let level = level.get();
561        let next = params(level);
562        if (level == 0) != (self.level == 0) {
563            // Finish the input waiting under the old level first.
564            self.process(true);
565            self.end_block(false);
566        } else if self.params.lazy_matching && !next.lazy_matching && self.match_available {
567            // Lazy matching holds the byte before `strstart` back; greedy
568            // matching does not know about it.
569            self.literal(self.win[self.strstart - 1]);
570            self.match_available = false;
571            self.block_full();
572        }
573        // No pending match crosses the change.
574        self.match_length = MIN_MATCH - 1;
575        self.prev_length = MIN_MATCH - 1;
576        self.level = level;
577        self.params = next;
578    }
579
580    /// Uncompressed bytes taken since the deflater was built or reset.
581    ///
582    /// # Examples
583    ///
584    /// ```
585    /// use compress_lib::deflate::{Deflater, Flush};
586    ///
587    /// let mut d = Deflater::default();
588    /// d.compress_vec(b"abc", &mut Vec::new(), Flush::Finish)?;
589    /// assert_eq!(d.total_in(), 3);
590    /// # Ok::<(), compress_lib::Error>(())
591    /// ```
592    #[must_use]
593    pub fn total_in(&self) -> u64 {
594        self.total_in
595    }
596
597    /// Compressed bytes handed out since the deflater was built or reset.
598    ///
599    /// # Examples
600    ///
601    /// ```
602    /// use compress_lib::deflate::{Deflater, Flush};
603    ///
604    /// let mut d = Deflater::default();
605    /// let mut out = Vec::new();
606    /// d.compress_vec(b"", &mut out, Flush::Finish)?;
607    /// assert_eq!(d.total_out(), out.len() as u64);
608    /// # Ok::<(), compress_lib::Error>(())
609    /// ```
610    #[must_use]
611    pub fn total_out(&self) -> u64 {
612        self.total_out
613    }
614
615    /// Heap bytes held: window, hash chains, symbols, pending output, and
616    /// block scratch.
617    ///
618    /// # Examples
619    ///
620    /// ```
621    /// let d = compress_lib::deflate::Deflater::default();
622    /// assert!(d.memory_in_use() > 64 * 1024);
623    /// ```
624    #[must_use]
625    pub fn memory_in_use(&self) -> usize {
626        self.win.capacity()
627            + 2 * (self.head.capacity() + self.prev.capacity())
628            + 4 * self.syms.capacity()
629            + self.pending.capacity()
630            + core::mem::size_of::<BlockScratch>()
631    }
632
633    /// Starts a new, unrelated stream, keeping the allocations.
634    ///
635    /// # Examples
636    ///
637    /// ```
638    /// use compress_lib::deflate::{self, Deflater, Flush};
639    ///
640    /// let mut d = Deflater::default();
641    /// let mut a = Vec::new();
642    /// d.compress_vec(b"first", &mut a, Flush::Finish)?;
643    /// d.reset();
644    /// let mut b = Vec::new();
645    /// d.compress_vec(b"second", &mut b, Flush::Finish)?;
646    /// assert_eq!(deflate::decompress(&b)?, b"second");
647    /// # Ok::<(), compress_lib::Error>(())
648    /// ```
649    pub fn reset(&mut self) {
650        // Clear only the hash heads this stream used when it was short and
651        // never slid (a small WebSocket message touches a few dozen of 32,768
652        // entries); otherwise clear them all.
653        let end = self.strstart + self.lookahead;
654        if self.total_in as usize + 1 < self.size && end < self.head.len() / 4 {
655            let shift = 32 - self.hash_bits;
656            for pos in 1..end.saturating_sub(MIN_MATCH - 1) {
657                self.head[hash3(load32(&self.win, pos), shift)] = 0;
658            }
659        } else {
660            self.head.fill(0);
661        }
662        self.strstart = 1;
663        self.lookahead = 0;
664        self.block_start = 1;
665        self.match_available = false;
666        self.match_length = MIN_MATCH - 1;
667        self.prev_length = MIN_MATCH - 1;
668        self.syms.clear();
669        self.pending.clear();
670        self.pending_pos = 0;
671        self.bitbuf = 0;
672        self.bitcnt = 0;
673        self.total_in = 0;
674        self.total_out = 0;
675        self.flush_written = false;
676        self.finished = false;
677    }
678
679    /// Zeroes the window (the plaintext history), the hash chains, the
680    /// symbol buffer, the pending output, and the block scratch, spare
681    /// capacity included, then resets the deflater for a new stream. For
682    /// connections that carried secrets: call it before the deflater is
683    /// dropped or reused. The allocations are kept.
684    ///
685    /// The zeroing goes through [`core::hint::black_box`] so it is not
686    /// removed as a dead store; without `unsafe` volatile writes that is a
687    /// strong hint to the compiler, not a guarantee.
688    ///
689    /// # Examples
690    ///
691    /// ```
692    /// use compress_lib::deflate::{Deflater, Flush};
693    ///
694    /// let mut d = Deflater::default();
695    /// d.compress_vec(b"password=hunter2", &mut Vec::new(), Flush::Sync)?;
696    /// d.wipe();
697    /// assert_eq!(d.total_in(), 0);
698    /// # Ok::<(), compress_lib::Error>(())
699    /// ```
700    pub fn wipe(&mut self) {
701        crate::wipe_vec(&mut self.win);
702        crate::wipe_vec(&mut self.head);
703        crate::wipe_vec(&mut self.prev);
704        crate::wipe_vec(&mut self.syms);
705        crate::wipe_vec(&mut self.pending);
706        *self.scratch = BlockScratch::new();
707        core::hint::black_box(&*self.scratch);
708        self.bitbuf = 0;
709        self.reset();
710    }
711
712    /// Presets the history with `dictionary` (its last `2^window_bits`
713    /// bytes): matches may refer into it. The decoder must be given the same
714    /// dictionary. Only before any input.
715    ///
716    /// # Errors
717    ///
718    /// [`ErrorKind::InvalidState`] after input has been given.
719    ///
720    /// # Examples
721    ///
722    /// ```
723    /// use compress_lib::deflate::{Deflater, Flush, Inflater};
724    ///
725    /// let dict = b"{\"type\":\"update\",\"value\":";
726    /// let mut d = Deflater::default();
727    /// d.set_dictionary(dict)?;
728    /// let mut packed = Vec::new();
729    /// d.compress_vec(b"{\"type\":\"update\",\"value\":42}", &mut packed, Flush::Finish)?;
730    /// let mut i = Inflater::new();
731    /// i.set_dictionary(dict)?;
732    /// let mut out = Vec::new();
733    /// i.finish_vec(&packed, &mut out)?;
734    /// assert_eq!(out, b"{\"type\":\"update\",\"value\":42}");
735    /// # Ok::<(), compress_lib::Error>(())
736    /// ```
737    pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<(), Error> {
738        if self.total_in != 0 || self.lookahead != 0 || self.strstart != 1 {
739            return Err(Error::config(ErrorKind::InvalidState));
740        }
741        let take = dictionary.len().min(self.wsize);
742        let dict = &dictionary[dictionary.len() - take..];
743        // Position 0 is the hash chains' "none", so the dictionary starts at 1.
744        self.win[1..1 + take].copy_from_slice(dict);
745        self.strstart = 1;
746        self.lookahead = take;
747        if self.level != 0 {
748            let end = 1 + take;
749            let mut pos = 1;
750            while pos + MIN_MATCH <= end {
751                self.insert(pos);
752                pos += 1;
753            }
754        }
755        self.strstart = 1 + take;
756        self.lookahead = 0;
757        self.block_start = self.strstart as isize;
758        Ok(())
759    }
760
761    /// Compresses as much of `input` as the window takes and writes
762    /// compressed bytes to `output`.
763    ///
764    /// With `Flush::None` the result is `NeedsInput` once all input is taken
765    /// (output may lag behind), or `NeedsOutput` when `output` is full.
766    /// With a flush, `Done` means all input is taken and the flush point is
767    /// completely in `output`; on `NeedsOutput`, call again with the same
768    /// flush and the input not yet consumed.
769    ///
770    /// # Errors
771    ///
772    /// [`ErrorKind::InvalidState`] when input is given after `Finish`
773    /// completed (call [`reset`](Deflater::reset) for a new stream).
774    ///
775    /// # Examples
776    ///
777    /// ```
778    /// use compress_lib::deflate::{self, Deflater, Flush, Status};
779    ///
780    /// let mut d = Deflater::default();
781    /// let mut out = [0u8; 256];
782    /// let p = d.compress(b"some data", &mut out, Flush::Finish)?;
783    /// assert_eq!(p.status, Status::Done);
784    /// assert_eq!(deflate::decompress(&out[..p.produced])?, b"some data");
785    /// # Ok::<(), compress_lib::Error>(())
786    /// ```
787    pub fn compress(
788        &mut self,
789        input: &[u8],
790        output: &mut [u8],
791        flush: Flush,
792    ) -> Result<Progress, Error> {
793        let mut consumed = 0;
794        let mut produced = 0;
795        if self.finished {
796            if !input.is_empty() {
797                return Err(Error::config(ErrorKind::InvalidState));
798            }
799            self.drain(output, &mut produced);
800            let status = if self.pending_left() == 0 {
801                Status::Done
802            } else {
803                Status::NeedsOutput
804            };
805            return Ok(Progress::new(0, produced, status));
806        }
807        loop {
808            self.drain(output, &mut produced);
809            if self.pending_left() > 0 {
810                return Ok(Progress::new(consumed, produced, Status::NeedsOutput));
811            }
812            if self.flush_written && consumed == input.len() {
813                self.flush_written = false;
814                if flush == Flush::Finish {
815                    self.finished = true;
816                }
817                return Ok(Progress::new(consumed, produced, Status::Done));
818            }
819            self.flush_written = false;
820            let before = (consumed, self.strstart, self.lookahead);
821            consumed += self.fill_window(&input[consumed..]);
822            let all_in = consumed == input.len();
823            let flushing = flush != Flush::None && all_in;
824            self.process(flushing);
825            if self.pending_left() > 0 {
826                continue;
827            }
828            if !all_in {
829                // Every round takes input or turns lookahead into output; a
830                // round that does neither would repeat forever. Fail closed.
831                if before == (consumed, self.strstart, self.lookahead) {
832                    return Err(Error::config(ErrorKind::InvalidState));
833                }
834                continue;
835            }
836            if flush == Flush::None {
837                return Ok(Progress::new(consumed, produced, Status::NeedsInput));
838            }
839            self.write_flush(flush);
840            self.flush_written = true;
841        }
842    }
843
844    /// Compresses `input` and appends to `out` until the flush point is
845    /// written (with `Flush::None`, until all input is taken). Returns
846    /// `Done`, or `NeedsInput` for `Flush::None`.
847    ///
848    /// # Errors
849    ///
850    /// As [`compress`](Deflater::compress), plus
851    /// [`ErrorKind::AllocationFailed`] when `out` cannot grow.
852    ///
853    /// # Examples
854    ///
855    /// ```
856    /// use compress_lib::deflate::{self, Deflater, Flush};
857    ///
858    /// let mut d = Deflater::default();
859    /// let mut out = Vec::new();
860    /// d.compress_vec(b"part one, ", &mut out, Flush::None)?;
861    /// d.compress_vec(b"part two", &mut out, Flush::Finish)?;
862    /// assert_eq!(deflate::decompress(&out)?, b"part one, part two");
863    /// # Ok::<(), compress_lib::Error>(())
864    /// ```
865    pub fn compress_vec(
866        &mut self,
867        input: &[u8],
868        out: &mut Vec<u8>,
869        flush: Flush,
870    ) -> Result<Progress, Error> {
871        let start = out.len();
872        let mut consumed = 0;
873        loop {
874            let have = out.len();
875            let room = (input.len() - consumed) / 2 + 1024;
876            if out.capacity() - have < room && out.try_reserve(room).is_err() {
877                return Err(Error::config(ErrorKind::AllocationFailed));
878            }
879            // Zero-fill only this step's room, not all spare capacity: the
880            // spare grows with the output, so filling it on every call
881            // would make many small calls quadratic (T-5).
882            out.resize(have + room, 0);
883            let p = self.compress(&input[consumed..], &mut out[have..], flush);
884            match p {
885                Ok(p) => {
886                    out.truncate(have + p.produced);
887                    consumed += p.consumed;
888                    if p.status != Status::NeedsOutput {
889                        return Ok(Progress::new(consumed, out.len() - start, p.status));
890                    }
891                }
892                Err(e) => {
893                    out.truncate(have);
894                    return Err(e);
895                }
896            }
897        }
898    }
899
900    fn pending_left(&self) -> usize {
901        self.pending.len() - self.pending_pos
902    }
903
904    /// Moves pending output into `output[*produced..]`.
905    fn drain(&mut self, output: &mut [u8], produced: &mut usize) {
906        let n = self.pending_left().min(output.len() - *produced);
907        output[*produced..*produced + n]
908            .copy_from_slice(&self.pending[self.pending_pos..self.pending_pos + n]);
909        self.pending_pos += n;
910        *produced += n;
911        self.total_out += n as u64;
912        if self.pending_pos == self.pending.len() {
913            self.pending.clear();
914            self.pending_pos = 0;
915        }
916    }
917
918    /// Copies input into the window, sliding it first when the lookahead
919    /// would not fit. Returns the bytes taken.
920    fn fill_window(&mut self, input: &[u8]) -> usize {
921        let size = self.size;
922        if size - self.strstart - self.lookahead < MIN_LOOKAHEAD
923            && self.strstart >= self.keep + self.wsize
924        {
925            self.slide();
926        }
927        let room = size - self.strstart - self.lookahead;
928        let n = room.min(input.len());
929        let at = self.strstart + self.lookahead;
930        self.win[at..at + n].copy_from_slice(&input[..n]);
931        self.lookahead += n;
932        self.total_in += n as u64;
933        n
934    }
935
936    /// Slides the window down by a whole number of windows, keeping at
937    /// least one window of history before `strstart`.
938    fn slide(&mut self) {
939        let shift = (self.strstart - self.keep) / self.wsize * self.wsize;
940        if shift == 0 {
941            return;
942        }
943        if self.level == 0 && self.block_start < shift as isize {
944            // Stored blocks are cut from the window; level 0 writes them
945            // before the data leaves.
946            self.end_block(false);
947        }
948        let end = self.strstart + self.lookahead;
949        self.win.copy_within(shift..end, 0);
950        self.strstart -= shift;
951        self.match_start = self.match_start.saturating_sub(shift);
952        self.prev_match = self.prev_match.saturating_sub(shift);
953        self.block_start -= shift as isize;
954        // Positions are below 2^16 and so is the shift; entries that slide
955        // out become 0, "none".
956        let s = shift as u32;
957        for h in self.head.iter_mut().chain(self.prev.iter_mut()) {
958            *h = u32::from(*h).saturating_sub(s) as u16;
959        }
960    }
961
962    /// Inserts `pos` into the hash chains; returns the previous head (0 for
963    /// none).
964    #[inline]
965    fn insert(&mut self, pos: usize) -> usize {
966        insert_at(
967            &mut self.head,
968            &mut self.prev,
969            &self.win,
970            pos,
971            32 - self.hash_bits,
972            self.wsize - 1,
973        )
974    }
975
976    /// Records a literal (set_level, flushes).
977    fn literal(&mut self, b: u8) {
978        self.syms.push(u32::from(b));
979        self.scratch.lit_freq[b as usize] += 1;
980    }
981
982    /// Ends the block when the symbol buffer is full. With a held-back
983    /// literal (lazy matching), the block stops before that byte.
984    #[inline]
985    fn block_full(&mut self) {
986        if self.syms.len() >= self.sym_cap {
987            let held = usize::from(self.match_available);
988            self.strstart -= held;
989            self.end_block(false);
990            self.strstart += held;
991        }
992    }
993
994    /// Turns the lookahead into symbols. Without `flushing`, stops while
995    /// fewer than `MIN_LOOKAHEAD` bytes wait (more input could extend a
996    /// match); with it, uses everything.
997    fn process(&mut self, flushing: bool) {
998        if self.level == 0 {
999            let chunk = STORED_CHUNK.min(self.size / 2);
1000            // A window too full to take more input and not yet able to slide
1001            // must be written out too, or the stream would stall.
1002            let full = self.strstart + self.lookahead + MIN_LOOKAHEAD > self.size;
1003            while self.lookahead >= chunk || ((flushing || full) && self.lookahead > 0) {
1004                let n = self.lookahead.min(65_535);
1005                self.strstart += n;
1006                self.lookahead -= n;
1007                self.end_block(false);
1008            }
1009            return;
1010        }
1011        loop {
1012            let used_up = if self.params.lazy_matching {
1013                self.lazy_run(flushing)
1014            } else {
1015                self.greedy_run(flushing)
1016            };
1017            self.block_full();
1018            if used_up {
1019                break;
1020            }
1021        }
1022        if flushing && self.match_available {
1023            self.literal(self.win[self.strstart - 1]);
1024            self.match_available = false;
1025            self.block_full();
1026        }
1027    }
1028
1029    /// Greedy matching (levels 1 to 3) with the hot state in locals. Runs
1030    /// until the lookahead is used up (`true`) or the symbol buffer is full
1031    /// (`false`).
1032    fn greedy_run(&mut self, flushing: bool) -> bool {
1033        let p = self.params;
1034        let wmask = self.wsize - 1;
1035        let keep = self.keep;
1036        let shift = 32 - self.hash_bits;
1037        let cap = self.sym_cap;
1038        let mut s = self.strstart;
1039        let mut look = self.lookahead;
1040        let mut misses = 0usize;
1041        let skip = self.level == 1;
1042        let win = &self.win[..];
1043        let head = &mut self.head[..];
1044        let prev = &mut self.prev[..];
1045        let syms = &mut self.syms;
1046        let freq = &mut *self.scratch;
1047        let used_up = loop {
1048            if look < MIN_LOOKAHEAD && (!flushing || look == 0) {
1049                break true;
1050            }
1051            if syms.len() >= cap {
1052                break false;
1053            }
1054            let mut len = 0;
1055            let mut start = 0;
1056            if look >= MIN_MATCH {
1057                let s4 = load32(win, s);
1058                let h = hash3(s4, shift);
1059                let mut cur = usize::from(head[h]);
1060                prev[s & wmask] = head[h];
1061                head[h] = s as u16;
1062                let max = MAX_MATCH.min(look);
1063                let mut chain = p.chain;
1064                while cur != 0 && cur < s && s - cur <= keep {
1065                    if (load32(win, cur) ^ s4) & 0x00FF_FFFF == 0 {
1066                        let l = MIN_MATCH
1067                            + common_prefix(win, cur + MIN_MATCH, s + MIN_MATCH, max - MIN_MATCH);
1068                        if l > len {
1069                            len = l;
1070                            start = cur;
1071                            if l >= p.nice.min(max) {
1072                                break;
1073                            }
1074                        }
1075                    }
1076                    chain -= 1;
1077                    if chain == 0 {
1078                        break;
1079                    }
1080                    let next = usize::from(prev[cur & wmask]);
1081                    if next >= cur {
1082                        break;
1083                    }
1084                    cur = next;
1085                }
1086            }
1087            if len >= MIN_MATCH {
1088                let dist = s - start;
1089                syms.push(((dist as u32) << 16) | (len - MIN_MATCH) as u32);
1090                freq.lit_freq[257 + LENGTH_CODE[len - MIN_MATCH] as usize] += 1;
1091                freq.dist_freq[dist_code(dist)] += 1;
1092                look -= len;
1093                misses = 0;
1094                if len <= p.lazy && look >= MIN_MATCH {
1095                    for _ in 1..len {
1096                        s += 1;
1097                        insert_at(head, prev, win, s, shift, wmask);
1098                    }
1099                    s += 1;
1100                } else {
1101                    s += len;
1102                }
1103            } else {
1104                let b = win[s];
1105                syms.push(u32::from(b));
1106                freq.lit_freq[b as usize] += 1;
1107                look -= 1;
1108                s += 1;
1109                misses += 1;
1110                // Level 1 on data that keeps missing (compressed or random
1111                // input): search only every few positions, more sparsely
1112                // the longer the run of misses (D-040).
1113                if skip && misses > 64 {
1114                    let extra = ((misses - 64) >> 4).min(15).min(look).min(cap - syms.len());
1115                    for &b in &win[s..s + extra] {
1116                        syms.push(u32::from(b));
1117                        freq.lit_freq[b as usize] += 1;
1118                    }
1119                    s += extra;
1120                    look -= extra;
1121                }
1122            }
1123        };
1124        self.strstart = s;
1125        self.lookahead = look;
1126        self.match_length = MIN_MATCH - 1;
1127        used_up
1128    }
1129
1130    /// Lazy matching (levels 4 to 9, zlib's deflate_slow) with the hot state
1131    /// in locals; returns as [`greedy_run`](Self::greedy_run).
1132    fn lazy_run(&mut self, flushing: bool) -> bool {
1133        let p = self.params;
1134        let wmask = self.wsize - 1;
1135        let keep = self.keep;
1136        let shift = 32 - self.hash_bits;
1137        let cap = self.sym_cap;
1138        let mut s = self.strstart;
1139        let mut look = self.lookahead;
1140        let mut available = self.match_available;
1141        let mut match_length = self.match_length;
1142        let mut match_start = self.match_start;
1143        let mut prev_length;
1144        let mut prev_match;
1145        let win = &self.win[..];
1146        let head = &mut self.head[..];
1147        let prev = &mut self.prev[..];
1148        let syms = &mut self.syms;
1149        let freq = &mut *self.scratch;
1150        let used_up = loop {
1151            if look < MIN_LOOKAHEAD && (!flushing || look == 0) {
1152                break true;
1153            }
1154            if syms.len() >= cap {
1155                break false;
1156            }
1157            let mut cur = 0;
1158            let mut s4 = 0;
1159            if look >= MIN_MATCH {
1160                s4 = load32(win, s);
1161                let h = hash3(s4, shift);
1162                cur = usize::from(head[h]);
1163                prev[s & wmask] = head[h];
1164                head[h] = s as u16;
1165            }
1166            prev_length = match_length;
1167            prev_match = match_start;
1168            match_length = MIN_MATCH - 1;
1169            if cur != 0 && prev_length < p.lazy && cur < s && s - cur <= keep {
1170                // Search for a match longer than the one held back.
1171                let max = MAX_MATCH.min(look);
1172                let nice = p.nice.min(max);
1173                let mut chain = if prev_length >= p.good {
1174                    p.chain >> 2
1175                } else {
1176                    p.chain
1177                };
1178                let mut best = prev_length;
1179                while cur != 0 && cur < s && s - cur <= keep && best < max {
1180                    // The two bytes ending a longer match first (zlib's scan
1181                    // end), then the first three.
1182                    if load16(win, cur + best - 1) == load16(win, s + best - 1)
1183                        && (load32(win, cur) ^ s4) & 0x00FF_FFFF == 0
1184                    {
1185                        let l = MIN_MATCH
1186                            + common_prefix(win, cur + MIN_MATCH, s + MIN_MATCH, max - MIN_MATCH);
1187                        if l > best {
1188                            best = l;
1189                            match_start = cur;
1190                            if l >= nice {
1191                                break;
1192                            }
1193                        }
1194                    }
1195                    chain -= 1;
1196                    if chain == 0 {
1197                        break;
1198                    }
1199                    let next = usize::from(prev[cur & wmask]);
1200                    if next >= cur {
1201                        break;
1202                    }
1203                    cur = next;
1204                }
1205                match_length = best.min(look);
1206                if match_length == MIN_MATCH && s - match_start > TOO_FAR {
1207                    match_length = MIN_MATCH - 1;
1208                }
1209            }
1210            if prev_length >= MIN_MATCH && match_length <= prev_length {
1211                let max_insert = s + look - MIN_MATCH;
1212                let dist = s - 1 - prev_match;
1213                syms.push(((dist as u32) << 16) | (prev_length - MIN_MATCH) as u32);
1214                freq.lit_freq[257 + LENGTH_CODE[prev_length - MIN_MATCH] as usize] += 1;
1215                freq.dist_freq[dist_code(dist)] += 1;
1216                look -= prev_length - 1;
1217                for _ in 0..prev_length - 2 {
1218                    s += 1;
1219                    if s <= max_insert {
1220                        insert_at(head, prev, win, s, shift, wmask);
1221                    }
1222                }
1223                available = false;
1224                match_length = MIN_MATCH - 1;
1225                s += 1;
1226            } else if available {
1227                let b = win[s - 1];
1228                syms.push(u32::from(b));
1229                freq.lit_freq[b as usize] += 1;
1230                s += 1;
1231                look -= 1;
1232            } else {
1233                available = true;
1234                s += 1;
1235                look -= 1;
1236            }
1237        };
1238        self.strstart = s;
1239        self.lookahead = look;
1240        self.match_available = available;
1241        self.match_length = match_length;
1242        self.match_start = match_start;
1243        self.prev_length = match_length;
1244        used_up
1245    }
1246
1247    // ---- bit output ----------------------------------------------------
1248
1249    #[inline]
1250    fn put(&mut self, value: u32, bits: u32) {
1251        self.bitbuf |= u64::from(value) << self.bitcnt;
1252        self.bitcnt += bits;
1253        if self.bitcnt >= 32 {
1254            self.pending
1255                .extend_from_slice(&(self.bitbuf as u32).to_le_bytes());
1256            self.bitbuf >>= 32;
1257            self.bitcnt -= 32;
1258        }
1259    }
1260
1261    /// Writes out whole bytes and pads the last one with zero bits.
1262    fn align(&mut self) {
1263        while self.bitcnt > 0 {
1264            self.pending.push(self.bitbuf as u8);
1265            self.bitbuf >>= 8;
1266            self.bitcnt = self.bitcnt.saturating_sub(8);
1267        }
1268        self.bitbuf = 0;
1269    }
1270
1271    fn write_flush(&mut self, flush: Flush) {
1272        match flush {
1273            Flush::None => {}
1274            Flush::Finish => {
1275                self.end_block(true);
1276                self.align();
1277            }
1278            Flush::Sync | Flush::Full => {
1279                self.end_block(false);
1280                // An empty stored block: header, pad, 00 00 FF FF.
1281                self.put(0, 3);
1282                self.align();
1283                self.pending.extend_from_slice(&[0, 0, 0xFF, 0xFF]);
1284                if flush == Flush::Full {
1285                    self.head.fill(0);
1286                    self.match_length = MIN_MATCH - 1;
1287                    self.prev_length = MIN_MATCH - 1;
1288                }
1289            }
1290        }
1291    }
1292
1293    /// Writes the current block (if it has data, or if it is the last) as
1294    /// the cheapest of stored, fixed, and dynamic.
1295    fn end_block(&mut self, last: bool) {
1296        let stored_len = (self.strstart as isize - self.block_start).max(0) as usize;
1297        if self.syms.is_empty() && stored_len == 0 && !last {
1298            return;
1299        }
1300        let stored_ok = self.block_start >= 0;
1301        if self.level == 0 && stored_ok {
1302            self.write_stored(self.block_start as usize, stored_len, last);
1303        } else {
1304            self.write_huffman_or_stored(stored_ok, stored_len, last);
1305        }
1306        self.syms.clear();
1307        self.scratch.lit_freq.fill(0);
1308        self.scratch.dist_freq.fill(0);
1309        self.block_start = self.strstart as isize;
1310    }
1311
1312    fn write_stored(&mut self, start: usize, len: usize, last: bool) {
1313        let mut at = start;
1314        let mut left = len;
1315        loop {
1316            let n = left.min(65_535);
1317            let final_piece = n == left;
1318            self.put(u32::from(last && final_piece), 1);
1319            self.put(0, 2);
1320            self.align();
1321            self.pending.extend_from_slice(&(n as u16).to_le_bytes());
1322            self.pending.extend_from_slice(&(!(n as u16)).to_le_bytes());
1323            self.pending.extend_from_slice(&self.win[at..at + n]);
1324            at += n;
1325            left -= n;
1326            if final_piece {
1327                break;
1328            }
1329        }
1330    }
1331
1332    fn write_huffman_or_stored(&mut self, stored_ok: bool, stored_len: usize, last: bool) {
1333        let s = &mut *self.scratch;
1334        s.lit_freq[256] = 1;
1335        // Every block gets at least two literal/length codes and two
1336        // distance codes, as zlib does, so no decoder meets the one-code
1337        // special case.
1338        let lit_used = s.lit_freq.iter().filter(|&&f| f != 0).count();
1339        if lit_used < 2 {
1340            s.lit_freq[if s.lit_freq[0] == 0 { 0 } else { 1 }] += 1;
1341        }
1342        let dist_used = s.dist_freq.iter().filter(|&&f| f != 0).count();
1343        if dist_used == 0 {
1344            s.dist_freq[0] = 1;
1345            s.dist_freq[1] = 1;
1346        } else if dist_used == 1 {
1347            let d = if s.dist_freq[0] == 0 { 0 } else { 1 };
1348            s.dist_freq[d] = 1;
1349        }
1350        huffman::lengths(&s.lit_freq, 15, &mut s.lit_lens);
1351        huffman::lengths(&s.dist_freq, 15, &mut s.dist_lens);
1352
1353        // Payload bits under each code; extra bits are the same for both.
1354        let mut extra: u64 = 0;
1355        let mut dyn_bits: u64 = 0;
1356        let mut fix_bits: u64 = 0;
1357        for sym in 0..286 {
1358            let f = u64::from(s.lit_freq[sym]);
1359            if f == 0 {
1360                continue;
1361            }
1362            dyn_bits += f * u64::from(s.lit_lens[sym]);
1363            fix_bits += f * u64::from(FIXED_LIT_LENS[sym]);
1364            if sym >= 257 {
1365                extra += f * u64::from(LENGTH_EXTRA[sym - 257]);
1366            }
1367        }
1368        for ((&f, &len), &x) in s.dist_freq.iter().zip(&s.dist_lens).zip(&DIST_EXTRA) {
1369            let f = u64::from(f);
1370            dyn_bits += f * u64::from(len);
1371            fix_bits += f * 5;
1372            extra += f * u64::from(x);
1373        }
1374        // The forced dummy symbols are counted above but never written: the
1375        // estimate is a few bits high for both codes alike.
1376        let hlit = 257
1377            + s.lit_lens[257..286]
1378                .iter()
1379                .rposition(|&l| l != 0)
1380                .map_or(0, |i| i + 1);
1381        let hdist = 1 + s.dist_lens.iter().rposition(|&l| l != 0).unwrap_or(0);
1382        rle_lengths(s, hlit, hdist);
1383        huffman::lengths(&s.pre_freq, 7, &mut s.pre_lens);
1384        let hclen = 4 + PRECODE_ORDER
1385            .iter()
1386            .rposition(|&i| s.pre_lens[i] != 0)
1387            .map_or(0, |i| (i + 1).saturating_sub(4));
1388        let mut header_bits = 14 + 3 * hclen as u64;
1389        for &(sym, _) in &s.rle[..s.rle_len] {
1390            header_bits += u64::from(s.pre_lens[sym as usize]);
1391            header_bits += match sym {
1392                16 => 2,
1393                17 => 3,
1394                18 => 7,
1395                _ => 0,
1396            };
1397        }
1398        let dynamic = 3 + header_bits + dyn_bits + extra;
1399        let fixed = 3 + fix_bits + extra;
1400        let pad = u64::from((8 - (self.bitcnt + 3) % 8) % 8);
1401        let pieces = (stored_len as u64).div_ceil(65_535).max(1);
1402        let stored = pieces * (3 + 32) + pad + 8 * stored_len as u64 + (pieces - 1) * 5;
1403
1404        if stored_ok && stored <= fixed.min(dynamic) {
1405            self.write_stored(self.block_start as usize, stored_len, last);
1406            return;
1407        }
1408        if fixed <= dynamic {
1409            self.put(u32::from(last), 1);
1410            self.put(1, 2);
1411            let mut lit_codes = [0u16; 288];
1412            huffman::codes(&FIXED_LIT_LENS, &mut lit_codes);
1413            let mut dist_codes = [0u16; 30];
1414            huffman::codes(&[5u8; 30], &mut dist_codes);
1415            self.write_symbols(&lit_codes, &FIXED_LIT_LENS, &dist_codes, &[5u8; 30]);
1416        } else {
1417            self.put(u32::from(last), 1);
1418            self.put(2, 2);
1419            self.put((hlit - 257) as u32, 5);
1420            self.put((hdist - 1) as u32, 5);
1421            self.put((hclen - 4) as u32, 4);
1422            let s = &mut *self.scratch;
1423            huffman::codes(&s.pre_lens, &mut s.pre_codes);
1424            huffman::codes(&s.lit_lens, &mut s.lit_codes[..286]);
1425            huffman::codes(&s.dist_lens, &mut s.dist_codes);
1426            for &i in &PRECODE_ORDER[..hclen] {
1427                let l = self.scratch.pre_lens[i];
1428                self.put(u32::from(l), 3);
1429            }
1430            for k in 0..self.scratch.rle_len {
1431                let (sym, value) = self.scratch.rle[k];
1432                let code = self.scratch.pre_codes[sym as usize];
1433                let len = self.scratch.pre_lens[sym as usize];
1434                self.put(u32::from(code), u32::from(len));
1435                match sym {
1436                    16 => self.put(u32::from(value), 2),
1437                    17 => self.put(u32::from(value), 3),
1438                    18 => self.put(u32::from(value), 7),
1439                    _ => {}
1440                }
1441            }
1442            let lit_codes = self.scratch.lit_codes;
1443            let lit_lens = self.scratch.lit_lens;
1444            let dist_codes = self.scratch.dist_codes;
1445            let dist_lens = self.scratch.dist_lens;
1446            self.write_symbols(&lit_codes, &lit_lens, &dist_codes, &dist_lens);
1447        }
1448    }
1449
1450    fn write_symbols(
1451        &mut self,
1452        lit_codes: &[u16],
1453        lit_lens: &[u8],
1454        dist_codes: &[u16],
1455        dist_lens: &[u8],
1456    ) {
1457        // The bit buffer lives in locals for the whole block; each symbol's
1458        // code and extra bits go out in one write (at most 20 bits for a
1459        // length, 28 for a distance).
1460        let mut bits = self.bitbuf;
1461        let mut count = self.bitcnt;
1462        let out = &mut self.pending;
1463        let mut put = |value: u64, n: u32| {
1464            bits |= value << count;
1465            count += n;
1466            if count >= 32 {
1467                out.extend_from_slice(&(bits as u32).to_le_bytes());
1468                bits >>= 32;
1469                count -= 32;
1470            }
1471        };
1472        for &sym in &self.syms {
1473            let dist = (sym >> 16) as usize;
1474            let litlen = (sym & 0xFFFF) as usize;
1475            if dist == 0 {
1476                put(u64::from(lit_codes[litlen]), u32::from(lit_lens[litlen]));
1477            } else {
1478                let code = LENGTH_CODE[litlen] as usize;
1479                let len_bits = u32::from(lit_lens[257 + code]);
1480                let extra = (litlen + MIN_MATCH - LENGTH_BASE[code] as usize) as u64;
1481                put(
1482                    u64::from(lit_codes[257 + code]) | (extra << len_bits),
1483                    len_bits + u32::from(LENGTH_EXTRA[code]),
1484                );
1485                let d = dist_code(dist);
1486                let dist_bits = u32::from(dist_lens[d]);
1487                let extra = (dist - DIST_BASE[d] as usize) as u64;
1488                put(
1489                    u64::from(dist_codes[d]) | (extra << dist_bits),
1490                    dist_bits + u32::from(DIST_EXTRA[d]),
1491                );
1492            }
1493        }
1494        put(u64::from(lit_codes[256]), u32::from(lit_lens[256]));
1495        self.bitbuf = bits;
1496        self.bitcnt = count;
1497    }
1498}
1499
1500/// Four bytes of `win` at `pos`, little-endian (the window is padded).
1501#[inline(always)]
1502fn load32(win: &[u8], pos: usize) -> u32 {
1503    let mut b = [0u8; 4];
1504    b.copy_from_slice(&win[pos..pos + 4]);
1505    u32::from_le_bytes(b)
1506}
1507
1508/// Two bytes of `win` at `pos`.
1509#[inline(always)]
1510fn load16(win: &[u8], pos: usize) -> u16 {
1511    u16::from_le_bytes([win[pos], win[pos + 1]])
1512}
1513
1514/// Hash of the low three bytes of `v` into `32 - shift` bits.
1515#[inline(always)]
1516fn hash3(v: u32, shift: u32) -> usize {
1517    ((v & 0x00FF_FFFF).wrapping_mul(0x9E37_79B1) >> shift) as usize
1518}
1519
1520/// Inserts `pos` into the chains; returns the previous head.
1521#[inline(always)]
1522fn insert_at(
1523    head: &mut [u16],
1524    prev: &mut [u16],
1525    win: &[u8],
1526    pos: usize,
1527    shift: u32,
1528    wmask: usize,
1529) -> usize {
1530    let h = hash3(load32(win, pos), shift);
1531    let old = head[h];
1532    prev[pos & wmask] = old;
1533    head[h] = pos as u16;
1534    usize::from(old)
1535}
1536
1537/// Bytes in common at `a` and `b` (`a < b`), at most `max`.
1538#[inline]
1539fn common_prefix(win: &[u8], a: usize, b: usize, max: usize) -> usize {
1540    let mut n = 0;
1541    while n + 8 <= max {
1542        let mut x = [0u8; 8];
1543        let mut y = [0u8; 8];
1544        x.copy_from_slice(&win[a + n..a + n + 8]);
1545        y.copy_from_slice(&win[b + n..b + n + 8]);
1546        let diff = u64::from_le_bytes(x) ^ u64::from_le_bytes(y);
1547        if diff != 0 {
1548            return n + (diff.trailing_zeros() / 8) as usize;
1549        }
1550        n += 8;
1551    }
1552    while n < max && win[a + n] == win[b + n] {
1553        n += 1;
1554    }
1555    n
1556}
1557
1558/// Run-length codes the literal/length lengths `[..hlit]` followed by the
1559/// distance lengths `[..hdist]` with symbols 16 (repeat previous 3 to 6), 17
1560/// (zeros 3 to 10), and 18 (zeros 11 to 138), and counts precode
1561/// frequencies.
1562fn rle_lengths(s: &mut BlockScratch, hlit: usize, hdist: usize) {
1563    let mut all = [0u8; 316];
1564    all[..hlit].copy_from_slice(&s.lit_lens[..hlit]);
1565    all[hlit..hlit + hdist].copy_from_slice(&s.dist_lens[..hdist]);
1566    let all = &all[..hlit + hdist];
1567    s.pre_freq = [0; 19];
1568    s.rle_len = 0;
1569    let push = |s: &mut BlockScratch, sym: u8, value: u8| {
1570        s.rle[s.rle_len] = (sym, value);
1571        s.rle_len += 1;
1572        s.pre_freq[sym as usize] += 1;
1573    };
1574    let mut i = 0;
1575    while i < all.len() {
1576        let v = all[i];
1577        let mut run = 1;
1578        while i + run < all.len() && all[i + run] == v {
1579            run += 1;
1580        }
1581        i += run;
1582        if v == 0 {
1583            while run >= 11 {
1584                let n = run.min(138);
1585                push(s, 18, (n - 11) as u8);
1586                run -= n;
1587            }
1588            if run >= 3 {
1589                push(s, 17, (run - 3) as u8);
1590                run = 0;
1591            }
1592            for _ in 0..run {
1593                push(s, 0, 0);
1594            }
1595        } else {
1596            push(s, v, 0);
1597            run -= 1;
1598            while run >= 3 {
1599                let n = run.min(6);
1600                push(s, 16, (n - 3) as u8);
1601                run -= n;
1602            }
1603            for _ in 0..run {
1604                push(s, v, 0);
1605            }
1606        }
1607    }
1608}
1609
1610#[cfg(test)]
1611mod tests {
1612    use super::*;
1613
1614    #[test]
1615    fn test_deflater_wipe_zeroes_every_buffer() {
1616        let mut d = Deflater::new(Level::DEFAULT);
1617        let mut out = Vec::new();
1618        d.compress_vec(&b"plaintext history ".repeat(500), &mut out, Flush::None)
1619            .unwrap();
1620        assert!(d.win.iter().any(|&b| b != 0));
1621        d.wipe();
1622        assert!(d.win.iter().all(|&b| b == 0));
1623        assert!(d.head.iter().all(|&h| h == 0));
1624        assert!(d.prev.iter().all(|&h| h == 0));
1625        assert!(d.syms.is_empty() && d.pending.is_empty());
1626        assert!(d.scratch.lit_freq.iter().all(|&f| f == 0));
1627        assert_eq!((d.total_in, d.bitbuf), (0, 0));
1628        let mut again = Vec::new();
1629        d.compress_vec(b"after", &mut again, Flush::Finish).unwrap();
1630        assert_eq!(crate::deflate::decompress(&again).unwrap(), b"after");
1631    }
1632
1633    #[test]
1634    fn test_wipe_vec_keeps_length_and_zeroes_contents() {
1635        // Spare capacity cannot be read back without `unsafe`; the length
1636        // and the visible elements can.
1637        let mut v: Vec<u8> = Vec::with_capacity(64);
1638        v.extend_from_slice(&[7; 40]);
1639        v.truncate(10);
1640        crate::wipe_vec(&mut v);
1641        assert_eq!(v.len(), 10);
1642        assert!(v.iter().all(|&b| b == 0));
1643        assert!(v.capacity() >= 64);
1644    }
1645}