1use alloc::vec::Vec;
2use core::cmp;
3#[cfg(not(feature = "std"))]
4use hashbrown::HashMap;
5#[cfg(feature = "std")]
6use std::collections::HashMap;
7
8use super::Code;
9use super::Lz77Encode;
10use super::Sink;
11
12#[derive(Debug)]
14pub struct DefaultLz77Encoder {
15 window_size: u16,
16 max_length: u16,
17 buf: Vec<u8>,
18}
19
20impl DefaultLz77Encoder {
21 pub fn new() -> Self {
31 DefaultLz77EncoderBuilder::new().build()
32 }
33
34 pub fn with_window_size(size: u16) -> Self {
47 DefaultLz77EncoderBuilder::new()
48 .window_size(cmp::min(size, super::MAX_WINDOW_SIZE))
49 .build()
50 }
51}
52
53impl Default for DefaultLz77Encoder {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl Lz77Encode for DefaultLz77Encoder {
60 fn encode<S>(&mut self, buf: &[u8], sink: S)
61 where
62 S: Sink,
63 {
64 self.buf.extend_from_slice(buf);
65 if self.buf.len() >= self.window_size as usize * 8 {
66 self.flush(sink);
67 }
68 }
69 fn flush<S>(&mut self, mut sink: S)
70 where
71 S: Sink,
72 {
73 let mut prefix_table = PrefixTable::new(self.buf.len());
74 let mut i = 0;
75 let end = cmp::max(3, self.buf.len()) - 3;
76 while i < end {
77 let key = prefix(&self.buf[i..]);
78 let matched = prefix_table.insert(key, i as u32);
79 if let Some(j) = matched.map(|j| j as usize) {
80 let distance = i - j;
81 if distance <= self.window_size as usize {
82 let length = 3 + longest_common_prefix(
83 &self.buf,
84 i + 3,
85 j + 3,
86 self.max_length as usize,
87 );
88 sink.consume(Code::Pointer {
89 length,
90 backward_distance: distance as u16,
91 });
92 for k in (i..).take(length as usize).skip(1) {
93 if k >= end {
94 break;
95 }
96 prefix_table.insert(prefix(&self.buf[k..]), k as u32);
97 }
98 i += length as usize;
99 continue;
100 }
101 }
102 sink.consume(Code::Literal(self.buf[i]));
103 i += 1;
104 }
105 for b in &self.buf[i..] {
106 sink.consume(Code::Literal(*b));
107 }
108 self.buf.clear();
109 }
110 fn window_size(&self) -> u16 {
111 self.window_size
112 }
113}
114
115#[inline]
116fn prefix(input_buf: &[u8]) -> [u8; 3] {
117 let buf: &[u8] = &input_buf[..3]; [buf[0], buf[1], buf[2]]
119}
120
121#[inline]
122fn longest_common_prefix(buf: &[u8], i: usize, j: usize, max: usize) -> u16 {
123 buf[i..]
124 .iter()
125 .take(max - 3)
126 .zip(&buf[j..])
127 .take_while(|&(x, y)| x == y)
128 .count() as u16
129}
130
131#[derive(Debug)]
132enum PrefixTable {
133 Small(HashMap<[u8; 3], u32>),
134 Large(LargePrefixTable),
135}
136impl PrefixTable {
137 fn new(bytes: usize) -> Self {
138 if bytes < super::MAX_WINDOW_SIZE as usize {
139 PrefixTable::Small(HashMap::new())
140 } else {
141 PrefixTable::Large(LargePrefixTable::new())
142 }
143 }
144
145 #[inline]
146 fn insert(&mut self, prefix: [u8; 3], position: u32) -> Option<u32> {
147 match *self {
148 PrefixTable::Small(ref mut x) => x.insert(prefix, position),
149 PrefixTable::Large(ref mut x) => x.insert(prefix, position),
150 }
151 }
152}
153
154#[derive(Debug)]
155struct LargePrefixTable {
156 table: Vec<Vec<(u8, u32)>>,
157}
158impl LargePrefixTable {
159 fn new() -> Self {
160 LargePrefixTable {
161 table: (0..=0xFFFF).map(|_| Vec::new()).collect(),
162 }
163 }
164
165 #[inline]
166 fn insert(&mut self, prefix: [u8; 3], position: u32) -> Option<u32> {
167 let p0 = prefix[0] as usize;
168 let p1 = prefix[1] as usize;
169 let p2 = prefix[2];
170
171 let i = (p0 << 8) + p1;
172 let positions = &mut self.table[i];
173 for &mut (key, ref mut value) in positions.iter_mut() {
174 if key == p2 {
175 let old = *value;
176 *value = position;
177 return Some(old);
178 }
179 }
180 positions.push((p2, position));
181 None
182 }
183}
184
185#[derive(Debug)]
202pub struct DefaultLz77EncoderBuilder {
203 window_size: u16,
204 max_length: u16,
205}
206
207impl DefaultLz77EncoderBuilder {
208 pub fn new() -> Self {
210 DefaultLz77EncoderBuilder {
211 window_size: super::MAX_WINDOW_SIZE,
212 max_length: super::MAX_LENGTH,
213 }
214 }
215
216 pub fn window_size(self, window_size: u16) -> Self {
223 DefaultLz77EncoderBuilder {
224 window_size: cmp::min(window_size, super::MAX_WINDOW_SIZE),
225 ..self
226 }
227 }
228
229 pub fn max_length(self, max_length: u16) -> Self {
235 DefaultLz77EncoderBuilder {
236 max_length: cmp::min(max_length, super::MAX_LENGTH),
237 ..self
238 }
239 }
240
241 pub fn build(self) -> DefaultLz77Encoder {
243 DefaultLz77Encoder {
244 window_size: self.window_size,
245 max_length: self.max_length,
246 buf: Vec::new(),
247 }
248 }
249}
250
251impl Default for DefaultLz77EncoderBuilder {
252 fn default() -> Self {
253 Self::new()
254 }
255}