1use 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;
17const MIN_LOOKAHEAD: usize = MAX_MATCH + MIN_MATCH + 1;
20const TOO_FAR: usize = 4096;
23const WIN_PAD: usize = 8;
26const 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
49static 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 t[255] = 28;
63 t
64};
65
66static 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
99const 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#[derive(Clone, Copy)]
121struct Params {
122 good: usize,
124 lazy: usize,
127 nice: usize,
129 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#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
158#[non_exhaustive]
159pub enum Flush {
160 None,
162 Sync,
166 Full,
169 Finish,
171}
172
173#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
190#[non_exhaustive]
191pub struct MemoryConfig {
192 hash_bits: u8,
194 block_symbols: usize,
196}
197
198impl MemoryConfig {
199 #[must_use]
207 pub const fn new() -> Self {
208 Self {
209 hash_bits: 0,
210 block_symbols: 0,
211 }
212 }
213
214 #[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 #[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 #[must_use]
266 pub const fn hash_bits(&self) -> u8 {
267 self.hash_bits
268 }
269
270 #[must_use]
278 pub const fn block_symbols(&self) -> usize {
279 self.block_symbols
280 }
281}
282
283struct 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 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
317pub struct Deflater {
336 memory: MemoryConfig,
337 level: u8,
338 params: Params,
339 window_bits: u8,
340 win: Vec<u8>,
342 size: usize,
345 wsize: usize,
346 keep: usize,
350 strstart: usize,
351 lookahead: usize,
352 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 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 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 #[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 let span = (8192 / wsize).max(2);
418 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 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 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 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 #[must_use]
513 pub fn with_memory(self, memory: MemoryConfig) -> Self {
514 Self::build(self.level, self.window_bits, memory)
515 }
516
517 #[must_use]
527 pub fn level(&self) -> Level {
528 Level::new(self.level).unwrap_or(Level::DEFAULT)
529 }
530
531 #[must_use]
539 pub fn window_bits(&self) -> u8 {
540 self.window_bits
541 }
542
543 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 self.process(true);
565 self.end_block(false);
566 } else if self.params.lazy_matching && !next.lazy_matching && self.match_available {
567 self.literal(self.win[self.strstart - 1]);
570 self.match_available = false;
571 self.block_full();
572 }
573 self.match_length = MIN_MATCH - 1;
575 self.prev_length = MIN_MATCH - 1;
576 self.level = level;
577 self.params = next;
578 }
579
580 #[must_use]
593 pub fn total_in(&self) -> u64 {
594 self.total_in
595 }
596
597 #[must_use]
611 pub fn total_out(&self) -> u64 {
612 self.total_out
613 }
614
615 #[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 pub fn reset(&mut self) {
650 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 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 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 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 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 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 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 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 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 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 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 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 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 #[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 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 #[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 fn process(&mut self, flushing: bool) {
998 if self.level == 0 {
999 let chunk = STORED_CHUNK.min(self.size / 2);
1000 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 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 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 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 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 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 #[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 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 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 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 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 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 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 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#[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#[inline(always)]
1510fn load16(win: &[u8], pos: usize) -> u16 {
1511 u16::from_le_bytes([win[pos], win[pos + 1]])
1512}
1513
1514#[inline(always)]
1516fn hash3(v: u32, shift: u32) -> usize {
1517 ((v & 0x00FF_FFFF).wrapping_mul(0x9E37_79B1) >> shift) as usize
1518}
1519
1520#[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#[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
1558fn 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 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}