lzma_rs/decode/
lzbuffer.rs

1use crate::error;
2use std::io;
3
4pub trait LzBuffer<W>
5where
6    W: io::Write,
7{
8    fn len(&self) -> usize;
9    // Retrieve the last byte or return a default
10    fn last_or(&self, lit: u8) -> u8;
11    // Retrieve the n-th last byte
12    fn last_n(&self, dist: usize) -> error::Result<u8>;
13    // Append a literal
14    fn append_literal(&mut self, lit: u8) -> error::Result<()>;
15    // Fetch an LZ sequence (length, distance) from inside the buffer
16    fn append_lz(&mut self, len: usize, dist: usize) -> error::Result<()>;
17    // Get a reference to the output sink
18    fn get_output(&self) -> &W;
19    // Get a mutable reference to the output sink
20    fn get_output_mut(&mut self) -> &mut W;
21    // Consumes this buffer and flushes any data
22    fn finish(self) -> io::Result<W>;
23    // Consumes this buffer without flushing any data
24    fn into_output(self) -> W;
25}
26
27// An accumulating buffer for LZ sequences
28pub struct LzAccumBuffer<W>
29where
30    W: io::Write,
31{
32    stream: W,       // Output sink
33    buf: Vec<u8>,    // Buffer
34    memlimit: usize, // Buffer memory limit
35    len: usize,      // Total number of bytes sent through the buffer
36}
37
38impl<W> LzAccumBuffer<W>
39where
40    W: io::Write,
41{
42    pub fn from_stream(stream: W, memlimit: usize) -> Self {
43        Self {
44            stream,
45            buf: Vec::new(),
46            memlimit,
47            len: 0,
48        }
49    }
50
51    // Append bytes
52    pub fn append_bytes(&mut self, buf: &[u8]) {
53        self.buf.extend_from_slice(buf);
54        self.len += buf.len();
55    }
56
57    // Reset the internal dictionary
58    pub fn reset(&mut self) -> io::Result<()> {
59        self.stream.write_all(self.buf.as_slice())?;
60        self.buf.clear();
61        self.len = 0;
62        Ok(())
63    }
64}
65
66impl<W> LzBuffer<W> for LzAccumBuffer<W>
67where
68    W: io::Write,
69{
70    fn len(&self) -> usize {
71        self.len
72    }
73
74    // Retrieve the last byte or return a default
75    fn last_or(&self, lit: u8) -> u8 {
76        let buf_len = self.buf.len();
77        if buf_len == 0 {
78            lit
79        } else {
80            self.buf[buf_len - 1]
81        }
82    }
83
84    // Retrieve the n-th last byte
85    fn last_n(&self, dist: usize) -> error::Result<u8> {
86        let buf_len = self.buf.len();
87        if dist > buf_len {
88            return Err(error::Error::LzmaError(format!(
89                "Match distance {} is beyond output size {}",
90                dist, buf_len
91            )));
92        }
93
94        Ok(self.buf[buf_len - dist])
95    }
96
97    // Append a literal
98    fn append_literal(&mut self, lit: u8) -> error::Result<()> {
99        let new_len = self.len + 1;
100
101        if new_len > self.memlimit {
102            Err(error::Error::LzmaError(format!(
103                "exceeded memory limit of {}",
104                self.memlimit
105            )))
106        } else {
107            self.buf.push(lit);
108            self.len = new_len;
109            Ok(())
110        }
111    }
112
113    // Fetch an LZ sequence (length, distance) from inside the buffer
114    fn append_lz(&mut self, len: usize, dist: usize) -> error::Result<()> {
115        lzma_debug!("LZ {{ len: {}, dist: {} }}", len, dist);
116        let buf_len = self.buf.len();
117        if dist > buf_len {
118            return Err(error::Error::LzmaError(format!(
119                "LZ distance {} is beyond output size {}",
120                dist, buf_len
121            )));
122        }
123
124        let mut offset = buf_len - dist;
125        for _ in 0..len {
126            let x = self.buf[offset];
127            self.buf.push(x);
128            offset += 1;
129        }
130        self.len += len;
131        Ok(())
132    }
133
134    // Get a reference to the output sink
135    fn get_output(&self) -> &W {
136        &self.stream
137    }
138
139    // Get a mutable reference to the output sink
140    fn get_output_mut(&mut self) -> &mut W {
141        &mut self.stream
142    }
143
144    // Consumes this buffer and flushes any data
145    fn finish(mut self) -> io::Result<W> {
146        self.stream.write_all(self.buf.as_slice())?;
147        self.stream.flush()?;
148        Ok(self.stream)
149    }
150
151    // Consumes this buffer without flushing any data
152    fn into_output(self) -> W {
153        self.stream
154    }
155}
156
157// A circular buffer for LZ sequences
158pub struct LzCircularBuffer<W>
159where
160    W: io::Write,
161{
162    stream: W,        // Output sink
163    buf: Vec<u8>,     // Circular buffer
164    dict_size: usize, // Length of the buffer
165    memlimit: usize,  // Buffer memory limit
166    cursor: usize,    // Current position
167    len: usize,       // Total number of bytes sent through the buffer
168}
169
170impl<W> LzCircularBuffer<W>
171where
172    W: io::Write,
173{
174    pub fn from_stream(stream: W, dict_size: usize, memlimit: usize) -> Self {
175        lzma_info!("Dict size in LZ buffer: {}", dict_size);
176        Self {
177            stream,
178            buf: Vec::new(),
179            dict_size,
180            memlimit,
181            cursor: 0,
182            len: 0,
183        }
184    }
185
186    fn get(&self, index: usize) -> u8 {
187        *self.buf.get(index).unwrap_or(&0)
188    }
189
190    fn set(&mut self, index: usize, value: u8) -> error::Result<()> {
191        let new_len = index + 1;
192
193        if self.buf.len() < new_len {
194            if new_len <= self.memlimit {
195                self.buf.resize(new_len, 0);
196            } else {
197                return Err(error::Error::LzmaError(format!(
198                    "exceeded memory limit of {}",
199                    self.memlimit
200                )));
201            }
202        }
203        self.buf[index] = value;
204        Ok(())
205    }
206}
207
208impl<W> LzBuffer<W> for LzCircularBuffer<W>
209where
210    W: io::Write,
211{
212    fn len(&self) -> usize {
213        self.len
214    }
215
216    // Retrieve the last byte or return a default
217    fn last_or(&self, lit: u8) -> u8 {
218        if self.len == 0 {
219            lit
220        } else {
221            self.get((self.dict_size + self.cursor - 1) % self.dict_size)
222        }
223    }
224
225    // Retrieve the n-th last byte
226    fn last_n(&self, dist: usize) -> error::Result<u8> {
227        if dist > self.dict_size {
228            return Err(error::Error::LzmaError(format!(
229                "Match distance {} is beyond dictionary size {}",
230                dist, self.dict_size
231            )));
232        }
233        if dist > self.len {
234            return Err(error::Error::LzmaError(format!(
235                "Match distance {} is beyond output size {}",
236                dist, self.len
237            )));
238        }
239
240        let offset = (self.dict_size + self.cursor - dist) % self.dict_size;
241        Ok(self.get(offset))
242    }
243
244    // Append a literal
245    fn append_literal(&mut self, lit: u8) -> error::Result<()> {
246        self.set(self.cursor, lit)?;
247        self.cursor += 1;
248        self.len += 1;
249
250        // Flush the circular buffer to the output
251        if self.cursor == self.dict_size {
252            self.stream.write_all(self.buf.as_slice())?;
253            self.cursor = 0;
254        }
255
256        Ok(())
257    }
258
259    // Fetch an LZ sequence (length, distance) from inside the buffer
260    fn append_lz(&mut self, len: usize, dist: usize) -> error::Result<()> {
261        lzma_debug!("LZ {{ len: {}, dist: {} }}", len, dist);
262        if dist > self.dict_size {
263            return Err(error::Error::LzmaError(format!(
264                "LZ distance {} is beyond dictionary size {}",
265                dist, self.dict_size
266            )));
267        }
268        if dist > self.len {
269            return Err(error::Error::LzmaError(format!(
270                "LZ distance {} is beyond output size {}",
271                dist, self.len
272            )));
273        }
274
275        let mut offset = (self.dict_size + self.cursor - dist) % self.dict_size;
276        for _ in 0..len {
277            let x = self.get(offset);
278            self.append_literal(x)?;
279            offset += 1;
280            if offset == self.dict_size {
281                offset = 0
282            }
283        }
284        Ok(())
285    }
286
287    // Get a reference to the output sink
288    fn get_output(&self) -> &W {
289        &self.stream
290    }
291
292    // Get a mutable reference to the output sink
293    fn get_output_mut(&mut self) -> &mut W {
294        &mut self.stream
295    }
296
297    // Consumes this buffer and flushes any data
298    fn finish(mut self) -> io::Result<W> {
299        if self.cursor > 0 {
300            self.stream.write_all(&self.buf[0..self.cursor])?;
301            self.stream.flush()?;
302        }
303        Ok(self.stream)
304    }
305
306    // Consumes this buffer without flushing any data
307    fn into_output(self) -> W {
308        self.stream
309    }
310}