1use std::io::{self, Read};
21
22use crate::block::{self, BLOCK_SIZE_MAX, FrameContext};
23use crate::decompress::{DecodeOptions, SKIPPABLE_MAGIC, SKIPPABLE_MAGIC_MASK, ZSTD_MAGIC};
24use crate::error::Error;
25use crate::frame;
26use crate::xxhash::Xxh64;
27
28const MAX_FRAME_HEADER: usize = 14;
31
32fn invalid(e: Error) -> io::Error {
34 io::Error::new(io::ErrorKind::InvalidData, e)
35}
36
37struct FrameState {
39 ctx: FrameContext,
40 win: Vec<u8>,
42 window: usize,
45 block_size_max: usize,
46 has_checksum: bool,
47 content_size: Option<u64>,
48 xxh: Xxh64,
49 produced: u64,
51}
52
53enum Phase {
54 FrameStart,
56 Skippable(usize),
58 Blocks,
60 Footer,
62 Done,
64}
65
66pub struct StreamDecoder<'d, R: Read> {
81 reader: R,
82 options: DecodeOptions<'d>,
83
84 in_buf: Vec<u8>,
87 in_pos: usize,
88 eof: bool,
89
90 phase: Phase,
91 frame: Option<FrameState>,
92
93 out_ready: Vec<u8>,
96 out_pos: usize,
97
98 total: u64,
100}
101
102impl<R: Read> StreamDecoder<'static, R> {
103 pub fn new(reader: R) -> Self {
106 Self::with_options(reader, DecodeOptions::new())
107 }
108}
109
110impl<'d, R: Read> StreamDecoder<'d, R> {
111 pub fn with_options(reader: R, options: DecodeOptions<'d>) -> Self {
114 StreamDecoder {
115 reader,
116 options,
117 in_buf: Vec::new(),
118 in_pos: 0,
119 eof: false,
120 phase: Phase::FrameStart,
121 frame: None,
122 out_ready: Vec::new(),
123 out_pos: 0,
124 total: 0,
125 }
126 }
127
128 fn compact(&mut self) {
130 if self.in_pos > 0 {
131 self.in_buf.drain(..self.in_pos);
132 self.in_pos = 0;
133 }
134 }
135
136 fn avail(&self) -> usize {
137 self.in_buf.len() - self.in_pos
138 }
139
140 fn fill(&mut self, n: usize) -> io::Result<bool> {
143 let mut tmp = [0u8; 1 << 16];
144 while self.avail() < n && !self.eof {
145 let got = self.reader.read(&mut tmp)?;
146 if got == 0 {
147 self.eof = true;
148 break;
149 }
150 self.in_buf.extend_from_slice(&tmp[..got]);
151 }
152 Ok(self.avail() >= n)
153 }
154
155 fn decode_more(&mut self) -> io::Result<bool> {
160 loop {
161 self.compact();
162 match self.phase {
163 Phase::Done => return Ok(false),
164 Phase::FrameStart => {
165 if !self.fill(4)? {
166 if self.avail() == 0 {
168 self.phase = Phase::Done;
169 return Ok(false);
170 }
171 return Err(invalid(Error::SrcSizeWrong));
172 }
173 let magic = u32::from_le_bytes(
174 self.in_buf[self.in_pos..self.in_pos + 4]
175 .try_into()
176 .unwrap(),
177 );
178 if magic == ZSTD_MAGIC {
179 self.in_pos += 4;
180 self.start_frame()?;
181 } else if magic & SKIPPABLE_MAGIC_MASK == SKIPPABLE_MAGIC {
182 if !self.fill(8)? {
183 return Err(invalid(Error::SrcSizeWrong));
184 }
185 let size = u32::from_le_bytes(
186 self.in_buf[self.in_pos + 4..self.in_pos + 8]
187 .try_into()
188 .unwrap(),
189 ) as usize;
190 self.in_pos += 8;
191 self.phase = Phase::Skippable(size);
192 } else {
193 return Err(invalid(Error::UnknownMagic(magic)));
194 }
195 }
196 Phase::Skippable(0) => self.phase = Phase::FrameStart,
197 Phase::Skippable(left) => {
198 if self.avail() == 0 && !self.fill(1)? {
199 return Err(invalid(Error::SrcSizeWrong));
200 }
201 let take = left.min(self.avail());
202 self.in_pos += take;
203 self.phase = Phase::Skippable(left - take);
204 }
205 Phase::Blocks => {
206 if self.decode_block()? {
207 return Ok(true);
208 }
209 }
210 Phase::Footer => self.finish_frame()?,
211 }
212 }
213 }
214
215 fn start_frame(&mut self) -> io::Result<()> {
217 let _ = self.fill(MAX_FRAME_HEADER)?; let header = match frame::parse(
219 &self.in_buf[self.in_pos..],
220 self.options.window_log_max_value(),
221 ) {
222 Ok(h) => h,
223 Err(Error::SrcSizeWrong) => return Err(invalid(Error::SrcSizeWrong)),
225 Err(e) => return Err(invalid(e)),
226 };
227
228 let dict = match (self.options.dictionary_value(), header.dict_id) {
231 (_, 0) => self.options.dictionary_value(),
232 (Some(d), id) if d.id() == id => Some(d),
233 (Some(d), id) => {
234 return Err(invalid(Error::DictionaryWrong {
235 expected: id,
236 actual: d.id(),
237 }));
238 }
239 (None, id) => return Err(invalid(Error::DictionaryRequired(id))),
240 };
241
242 self.in_pos += header.header_len;
243
244 let mut win = Vec::new();
245 if let Some(d) = dict {
246 win.extend_from_slice(d.content());
247 }
248 let window = header.window_size.min(usize::MAX as u64) as usize;
249 self.frame = Some(FrameState {
250 ctx: FrameContext::with_dictionary(dict),
251 win,
252 window,
253 block_size_max: header.window_size.min(BLOCK_SIZE_MAX as u64) as usize,
254 has_checksum: header.has_checksum,
255 content_size: header.content_size,
256 xxh: Xxh64::new(0),
257 produced: 0,
258 });
259 self.phase = Phase::Blocks;
260 Ok(())
261 }
262
263 fn decode_block(&mut self) -> io::Result<bool> {
266 if !self.fill(3)? {
267 return Err(invalid(Error::SrcSizeWrong));
268 }
269 let p = self.in_pos;
270 let raw = u32::from(self.in_buf[p])
271 | u32::from(self.in_buf[p + 1]) << 8
272 | u32::from(self.in_buf[p + 2]) << 16;
273 let last = raw & 1 != 0;
274 let block_type = (raw >> 1) & 3;
275 let size = (raw >> 3) as usize;
276 self.in_pos += 3;
277
278 let body_needed = match block_type {
279 1 => 1, 0 | 2 => size, _ => return Err(invalid(Error::BlockTypeInvalid)),
282 };
283 if !self.fill(body_needed)? {
284 return Err(invalid(Error::SrcSizeWrong));
285 }
286
287 let block_size_max = self.frame.as_ref().unwrap().block_size_max;
288 if size > block_size_max {
289 return Err(invalid(Error::Corrupted(
290 "block size exceeds block size limit",
291 )));
292 }
293
294 let body_start = self.in_pos;
295 let fr = self.frame.as_mut().unwrap();
296 let before = fr.win.len();
297 match block_type {
298 0 => {
300 fr.win
301 .extend_from_slice(&self.in_buf[body_start..body_start + size]);
302 self.in_pos += size;
303 }
304 1 => {
306 let byte = self.in_buf[body_start];
307 fr.win.resize(fr.win.len() + size, byte);
308 self.in_pos += 1;
309 }
310 _ => {
314 let body = &self.in_buf[body_start..body_start + size];
315 block::decode_compressed_block(
316 &mut fr.ctx,
317 body,
318 &mut fr.win,
319 0,
320 &[],
321 block_size_max,
322 usize::MAX,
323 )
324 .map_err(invalid)?;
325 self.in_pos += size;
326 }
327 }
328
329 let new = &fr.win[before..];
332 self.total += new.len() as u64;
333 if self.total > self.options.limit_value() as u64 {
334 return Err(invalid(Error::OutputTooLarge));
335 }
336 self.out_ready.extend_from_slice(new);
337 fr.xxh.update(new);
338 fr.produced += new.len() as u64;
339
340 if fr.win.len() > fr.window {
343 let drop = fr.win.len() - fr.window;
344 fr.win.drain(..drop);
345 }
346
347 if last {
348 self.phase = Phase::Footer;
349 }
350 Ok(!self.out_ready.is_empty())
351 }
352
353 fn finish_frame(&mut self) -> io::Result<()> {
355 let fr = self.frame.take().expect("frame state present in Footer");
356
357 if let Some(fcs) = fr.content_size {
358 if fr.produced != fcs {
359 return Err(invalid(Error::FrameContentSizeMismatch));
360 }
361 }
362
363 if fr.has_checksum {
364 if !self.fill(4)? {
365 return Err(invalid(Error::SrcSizeWrong));
366 }
367 let stored = u32::from_le_bytes(
368 self.in_buf[self.in_pos..self.in_pos + 4]
369 .try_into()
370 .unwrap(),
371 );
372 self.in_pos += 4;
373 let actual = fr.xxh.digest() as u32;
374 if stored != actual {
375 return Err(invalid(Error::ChecksumMismatch {
376 expected: stored,
377 actual,
378 }));
379 }
380 }
381
382 self.phase = Phase::FrameStart;
383 Ok(())
384 }
385}
386
387impl<R: Read> Read for StreamDecoder<'_, R> {
388 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
389 if buf.is_empty() {
390 return Ok(0);
391 }
392 loop {
393 if self.out_pos < self.out_ready.len() {
394 let n = (self.out_ready.len() - self.out_pos).min(buf.len());
395 buf[..n].copy_from_slice(&self.out_ready[self.out_pos..self.out_pos + n]);
396 self.out_pos += n;
397 return Ok(n);
398 }
399 self.out_ready.clear();
400 self.out_pos = 0;
401 if !self.decode_more()? {
402 return Ok(0);
403 }
404 }
405 }
406}