structured_zstd/decoding/streaming_decoder.rs
1//! The [StreamingDecoder] wraps a [FrameDecoder] and provides a Read impl that decodes data when necessary
2
3use core::borrow::BorrowMut;
4
5use crate::common::MAX_BLOCK_SIZE;
6use crate::decoding::errors::{FrameDecoderError, ReadFrameHeaderError};
7use crate::decoding::{BlockDecodingStrategy, DictionaryHandle, FrameDecoder};
8use crate::io::{Error, ErrorKind, Read};
9
10/// High level Zstandard frame decoder that can be used to decompress a given Zstandard frame.
11///
12/// This decoder implements `io::Read`, so you can interact with it by calling
13/// `io::Read::read_to_end` / `io::Read::read_exact` or passing this to another library / module as a source for the decoded content
14///
15/// If you need more control over how decompression takes place, you can use
16/// the lower level [FrameDecoder], which allows for greater control over how
17/// decompression takes place but the implementor must call
18/// [FrameDecoder::decode_blocks] repeatedly to decode the entire frame.
19///
20/// ## Multiple frames
21/// A stream is one or more frames (RFC 8878 3). Every read path, plain `read`
22/// and `io::copy` over it included, decodes them in turn, skips skippable
23/// frames wherever they stand, and applies the constructor's dictionary to
24/// each frame. The source ending at a frame boundary ends the stream; bytes
25/// that do not form a frame are an error. `read` hands back a finished frame's
26/// bytes before it reads the next frame's header, so a source that stays open
27/// is not waited on while output is pending.
28///
29/// To decode a single frame and leave the bytes after it unread, drive a
30/// [FrameDecoder] directly.
31///
32/// ```no_run
33/// // `File` is std-only; `read_to_end` itself is available under no_std too.
34/// #[cfg(feature = "std")]
35/// {
36/// use std::fs::File;
37/// use std::io::Read;
38/// use structured_zstd::decoding::StreamingDecoder;
39///
40/// // Read a Zstandard archive from the filesystem then decompress it into a vec.
41/// let mut f: File = todo!("Read a .zstd archive from somewhere");
42/// let mut decoder = StreamingDecoder::new(f).unwrap();
43/// let mut result = Vec::new();
44/// Read::read_to_end(&mut decoder, &mut result).unwrap();
45/// }
46/// ```
47pub struct StreamingDecoder<READ: Read, DEC: BorrowMut<FrameDecoder>> {
48 pub decoder: DEC,
49 source: READ,
50 /// Whether the decoder was constructed with a dictionary it applies to
51 /// every frame. The `read_to_end` paths re-initialise FOLLOWING
52 /// concatenated frames with it (a plain re-init resolves dictionaries by
53 /// frame id only and would lose it for frames omitting the id); the
54 /// decoder already holds its handle, so this one keeps none of its own.
55 forced_dictionary: bool,
56 /// The source has ended at a frame boundary (or held only skippable
57 /// frames): every read from here on is the end of the stream, without
58 /// asking the source again.
59 exhausted: bool,
60 /// Source bytes read ahead and not yet decoded.
61 input: Input,
62}
63
64/// The most of a skippable frame's content read in one step.
65const SKIP_CHUNK: u32 = 8 * 1024;
66
67/// Source bytes of the decoder's next step, gathered the way upstream zstd's
68/// `ZSTD_decompressStream` loads `nextSrcSizeToDecompress` bytes: exactly the
69/// next frame header, block or checksum, and nothing past it. A step is decoded
70/// only once it is all in hand, so a non-blocking source that returns
71/// `WouldBlock` part-way through loses nothing, and the source never stands
72/// beyond what the decoder has taken. A Raw block's content is the exception:
73/// it is read straight into the decoder's buffer, see [`RawBlock`].
74struct Input {
75 /// Grown to the largest step seen; holds the pending bytes at
76 /// `start..end`.
77 buf: alloc::vec::Vec<u8>,
78 start: usize,
79 end: usize,
80 /// Content of a skippable frame still to step over.
81 skip_left: u32,
82 /// The Raw block whose content is being read.
83 raw: Option<RawBlock>,
84}
85
86/// A Raw block in progress. Its content is the output itself, so it is not
87/// gathered whole: each read lands in a [`RAW_CHUNK`] of the input buffer,
88/// still in cache, and goes on to the decode buffer at once.
89struct RawBlock {
90 size: u32,
91 left: u32,
92 last: bool,
93 /// The running digest of the block, when per-block checksums are asked
94 /// for: its content may be handed on before the block ends, so it cannot
95 /// be hashed from the decode buffer at the end as other blocks are.
96 #[cfg(all(feature = "lsm", feature = "hash"))]
97 digest: Option<twox_hash::XxHash64>,
98}
99
100/// The most of a Raw block read in one step. Every byte of the input buffer
101/// is initialised once, when it first grows, so a source that hands content
102/// over in small pieces costs a copy of each piece and nothing more.
103const RAW_CHUNK: usize = 32 * 1024;
104
105impl Input {
106 const fn new() -> Self {
107 Self {
108 buf: alloc::vec::Vec::new(),
109 start: 0,
110 end: 0,
111 skip_left: 0,
112 raw: None,
113 }
114 }
115
116 fn pending(&self) -> &[u8] {
117 &self.buf[self.start..self.end]
118 }
119
120 /// Read the rest of `source` behind the pending bytes. What it reads stays
121 /// pending whatever it returns, so a source that stops part-way through
122 /// is retried from where it stopped, with nothing lost.
123 fn read_rest<R: Read>(&mut self, source: &mut R) -> Result<(), Error> {
124 if self.start > 0 {
125 self.buf.copy_within(self.start..self.end, 0);
126 self.end -= self.start;
127 self.start = 0;
128 }
129 self.buf.truncate(self.end);
130 // Both `read_to_end`s keep what they appended when they fail.
131 let result = source.read_to_end(&mut self.buf);
132 self.end = self.buf.len();
133 result.map(drop)
134 }
135
136 /// Read the next part of a Raw block, at most `left` bytes and at most
137 /// [`RAW_CHUNK`], into the start of the buffer and return how many. Only
138 /// called while nothing is pending. `Ok(0)` is the source's end;
139 /// `Interrupted` is retried.
140 fn read_raw<R: Read>(&mut self, source: &mut R, left: u32) -> Result<usize, Error> {
141 debug_assert!(
142 self.pending().is_empty(),
143 "a Raw block is read with nothing pending"
144 );
145 // `RAW_CHUNK` fits a `u32`, so the minimum is taken in the wire's width.
146 let chunk = left.min(RAW_CHUNK as u32) as usize;
147 if self.buf.len() < chunk {
148 self.buf.resize(chunk, 0);
149 }
150 loop {
151 match source.read(&mut self.buf[..chunk]) {
152 Err(e) if e.kind() == ErrorKind::Interrupted => {}
153 other => return other,
154 }
155 }
156 }
157
158 /// Drop the input, buffer and all: after `read_rest` it holds a whole
159 /// stream, which a decoder kept alive must not pin.
160 fn release(&mut self) {
161 self.buf = alloc::vec::Vec::new();
162 self.start = 0;
163 self.end = 0;
164 }
165
166 fn consume(&mut self, n: usize) {
167 debug_assert!(n <= self.end - self.start);
168 self.start += n;
169 if self.start == self.end {
170 self.start = 0;
171 self.end = 0;
172 }
173 }
174
175 /// Read more of `source` behind the pending bytes, up to `want` pending in
176 /// all and no further. `Ok(0)` is its end; its errors come back as it
177 /// reported them, `Interrupted` retried.
178 fn fill<R: Read>(&mut self, source: &mut R, want: usize) -> Result<usize, Error> {
179 // Pending bytes are an unfinished step, which reads stop at, so they
180 // are rarely moved; when they are, they are less than one step.
181 if self.start > 0 {
182 self.buf.copy_within(self.start..self.end, 0);
183 self.end -= self.start;
184 self.start = 0;
185 }
186 debug_assert!(self.end < want, "a fill must ask for more than is pending");
187 if self.buf.len() < want {
188 // Doubling keeps a stream of growing blocks to a few allocations.
189 let len = want.max(2 * self.buf.len());
190 self.buf.resize(len, 0);
191 }
192 loop {
193 match source.read(&mut self.buf[self.end..want]) {
194 Ok(n) => {
195 self.end += n;
196 return Ok(n);
197 }
198 Err(e) if e.kind() == ErrorKind::Interrupted => {}
199 Err(e) => return Err(e),
200 }
201 }
202 }
203}
204
205/// How much of a frame header `bytes` says there is to read: 4 for the magic,
206/// 8 for a skippable frame's header, and for a frame its descriptor's fields.
207/// A magic that is neither stops at 4, where the parser rejects it. A
208/// magicless frame (`ZSTD_f_zstd1_magicless`) starts at its descriptor and
209/// has no skippable form.
210fn header_len(bytes: &[u8], magicless: bool) -> usize {
211 let descriptor_at = if magicless {
212 0
213 } else {
214 let Some(magic) = bytes.first_chunk::<4>() else {
215 return 4;
216 };
217 let magic = u32::from_le_bytes(*magic);
218 if magic & 0xFFFF_FFF0 == 0x184D_2A50 {
219 return 8;
220 }
221 if magic != crate::common::MAGIC_NUM {
222 return 4;
223 }
224 4
225 };
226 let Some(&descriptor) = bytes.get(descriptor_at) else {
227 return descriptor_at + 1;
228 };
229 let descriptor = crate::decoding::frame::FrameDescriptor(descriptor);
230 let window = usize::from(!descriptor.single_segment_flag());
231 let dict = descriptor.dictionary_id_bytes().map_or(0, usize::from);
232 let fcs = descriptor.frame_content_size_bytes().map_or(0, usize::from);
233 descriptor_at + 1 + window + dict + fcs
234}
235
236impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
237 pub fn new_with_decoder(
238 mut source: READ,
239 mut decoder: DEC,
240 ) -> Result<StreamingDecoder<READ, DEC>, FrameDecoderError> {
241 let started = start_first_frame(decoder.borrow_mut(), &mut source, FrameStart::Plain)?;
242 Ok(StreamingDecoder {
243 decoder,
244 source,
245 forced_dictionary: false,
246 exhausted: !started,
247 input: Input::new(),
248 })
249 }
250
251 /// [`new_with_decoder`](Self::new_with_decoder) with `dict` applied to
252 /// the frame even when its header omits the dictionary ID, as
253 /// [`new_with_dictionary_handle`](StreamingDecoder::new_with_dictionary_handle)
254 /// applies it (same warning). A decoder reused frame after frame keeps its
255 /// buffers and, for the same dictionary, the handle it already holds, so
256 /// after the first frame it allocates nothing and touches no reference
257 /// count.
258 ///
259 /// # Examples
260 /// ```
261 /// use std::io::Read;
262 /// use structured_zstd::decoding::{Dictionary, DictionaryHandle, FrameDecoder, StreamingDecoder};
263 /// use structured_zstd::encoding::{FrameCompressor, CompressionLevel};
264 ///
265 /// let content = b"a dictionary of words the frames reuse".to_vec();
266 /// let dictionary = DictionaryHandle::from_dictionary(
267 /// Dictionary::from_raw_content(1, content.clone()).unwrap(),
268 /// );
269 /// let mut compressor: FrameCompressor = FrameCompressor::new(CompressionLevel::Default);
270 /// compressor.set_dictionary(Dictionary::from_raw_content(1, content).unwrap()).unwrap();
271 /// let frame = compressor.compress_independent_frame(b"the frames reuse words");
272 ///
273 /// let mut decoder = FrameDecoder::new();
274 /// for _ in 0..2 {
275 /// let mut stream =
276 /// StreamingDecoder::new_with_decoder_and_dictionary_handle(&frame[..], &mut decoder, &dictionary)
277 /// .unwrap();
278 /// let mut decoded = Vec::new();
279 /// stream.read_to_end(&mut decoded).unwrap();
280 /// assert_eq!(decoded, b"the frames reuse words");
281 /// }
282 /// ```
283 pub fn new_with_decoder_and_dictionary_handle(
284 mut source: READ,
285 mut decoder: DEC,
286 dict: &DictionaryHandle,
287 ) -> Result<StreamingDecoder<READ, DEC>, FrameDecoderError> {
288 let started = start_first_frame(
289 decoder.borrow_mut(),
290 &mut source,
291 FrameStart::Dictionary(dict),
292 )?;
293 Ok(StreamingDecoder {
294 decoder,
295 source,
296 forced_dictionary: true,
297 exhausted: !started,
298 input: Input::new(),
299 })
300 }
301}
302
303impl<READ: Read> StreamingDecoder<READ, FrameDecoder> {
304 pub fn new(
305 mut source: READ,
306 ) -> Result<StreamingDecoder<READ, FrameDecoder>, FrameDecoderError> {
307 let mut decoder = FrameDecoder::new();
308 let started = start_first_frame(&mut decoder, &mut source, FrameStart::Plain)?;
309 Ok(StreamingDecoder {
310 decoder,
311 source,
312 forced_dictionary: false,
313 exhausted: !started,
314 input: Input::new(),
315 })
316 }
317
318 /// Create a streaming decoder using a pre-parsed dictionary handle.
319 ///
320 /// # Warning
321 ///
322 /// This constructor initializes the underlying [`FrameDecoder`] with
323 /// `dict`, even if a frame header omits the optional dictionary ID.
324 /// Callers must only use it when they already know the stream was encoded
325 /// with this dictionary; otherwise decoded output can be silently
326 /// corrupted.
327 pub fn new_with_dictionary_handle(
328 source: READ,
329 dict: &DictionaryHandle,
330 ) -> Result<StreamingDecoder<READ, FrameDecoder>, FrameDecoderError> {
331 Self::new_with_decoder_and_dictionary_handle(source, FrameDecoder::new(), dict)
332 }
333
334 /// Create a streaming decoder using a serialized dictionary blob.
335 ///
336 /// # Warning
337 ///
338 /// This API forwards to [`StreamingDecoder::new_with_dictionary_handle`]
339 /// and therefore applies the decoded dictionary to frames whose headers may
340 /// omit the optional dictionary ID. Only use it when the stream is known to
341 /// be encoded with that dictionary.
342 pub fn new_with_dictionary_bytes(
343 source: READ,
344 raw_dictionary: &[u8],
345 ) -> Result<StreamingDecoder<READ, FrameDecoder>, FrameDecoderError> {
346 let dict = DictionaryHandle::decode_dict(raw_dictionary)?;
347 Self::new_with_dictionary_handle(source, &dict)
348 }
349}
350
351impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
352 /// Gets a reference to the underlying reader.
353 pub fn get_ref(&self) -> &READ {
354 &self.source
355 }
356
357 /// Gets a mutable reference to the underlying reader.
358 ///
359 /// It is inadvisable to directly read from the underlying reader.
360 pub fn get_mut(&mut self) -> &mut READ {
361 &mut self.source
362 }
363
364 /// Gets a mutable reference to the frame decoder driving this stream.
365 ///
366 /// Exposed for settings that are read as decoding proceeds rather than at
367 /// construction — [`FrameDecoder::set_content_checksum`] above all, which a
368 /// caller that wants mismatches to fail (rather than merely be computed)
369 /// has to reach after the constructor has chosen and initialised the
370 /// decoder, including on the dictionary paths.
371 pub fn decoder_mut(&mut self) -> &mut FrameDecoder {
372 self.decoder.borrow_mut()
373 }
374
375 /// Destructures this object into the inner reader.
376 ///
377 /// The decoder reads only what its next step needs, so once a frame's
378 /// content has been delivered the reader stands right after that frame.
379 /// Bytes of a step a `WouldBlock` left unfinished stay with the decoder.
380 pub fn into_inner(self) -> READ
381 where
382 READ: Sized,
383 {
384 self.source
385 }
386
387 /// Destructures this object into both the inner reader and [FrameDecoder].
388 pub fn into_parts(self) -> (READ, DEC)
389 where
390 READ: Sized,
391 {
392 (self.source, self.decoder)
393 }
394
395 /// Destructures this object into the inner [FrameDecoder].
396 pub fn into_frame_decoder(self) -> DEC {
397 self.decoder
398 }
399
400 /// The error for a source that ended inside a frame. Cut inside the
401 /// trailing checksum, that is what it reports; cut inside a block, the
402 /// leftover input goes to the block decoder, which reports how it was cut
403 /// short as it does for any truncated frame. Whole input never reaches
404 /// here (it would have decoded), so that decode fails; were it to pass,
405 /// the cut is still reported, as an early end of input.
406 fn cut_short(&mut self) -> Error {
407 let decoder = self.decoder.borrow_mut();
408 if decoder.awaits_checksum() {
409 return frame_error(FrameDecoderError::FailedToReadChecksum(Error::from(
410 ErrorKind::UnexpectedEof,
411 )));
412 }
413 let mut rest = self.input.pending();
414 decoder
415 .decode_blocks(&mut rest, BlockDecodingStrategy::All)
416 .map_or_else(frame_error, |_| Error::from(ErrorKind::UnexpectedEof))
417 }
418
419 /// Start the frame that follows the finished one, skipping skippable
420 /// frames, with the constructor's dictionary if it had one. `false` when
421 /// the source ends cleanly at the frame boundary; anything else that is
422 /// not a frame is an error.
423 ///
424 /// The source's own errors go back as it reported them, so a non-blocking
425 /// source's `WouldBlock` stays one; what the boundary had read stays in
426 /// [`Input`], and the header is parsed only once it is whole, so a retry
427 /// resumes where the source stopped.
428 fn start_next_frame(&mut self) -> Result<bool, Error> {
429 let how = if self.forced_dictionary {
430 FrameStart::HeldDictionary
431 } else {
432 FrameStart::Plain
433 };
434 let magicless = self.decoder.borrow_mut().is_magicless();
435 loop {
436 while self.input.skip_left > 0 {
437 // Counted in the wire's `u32`; a step is at most `SKIP_CHUNK`,
438 // which every `usize` holds.
439 let step = self.input.skip_left.min(SKIP_CHUNK);
440 if self.input.pending().is_empty()
441 && self.input.fill(&mut self.source, step as usize)? == 0
442 {
443 return Err(frame_error(FrameDecoderError::FailedToSkipFrame));
444 }
445 // Reads stop at `step`, so what is pending is skippable content;
446 // the minimum is taken in `u32`, the wire's width.
447 let pending = u32::try_from(self.input.pending().len()).unwrap_or(u32::MAX);
448 let take = self.input.skip_left.min(pending);
449 self.input.consume(take as usize);
450 self.input.skip_left -= take;
451 }
452 loop {
453 let have = self.input.pending().len();
454 let want = header_len(self.input.pending(), magicless);
455 if have >= want {
456 break;
457 }
458 if self.input.fill(&mut self.source, want)? == 0 {
459 if have == 0 {
460 return Ok(false);
461 }
462 // The source ended inside a header: let the parser report
463 // it as it reports any header cut short.
464 break;
465 }
466 }
467 let mut header = self.input.pending();
468 let before = header.len();
469 let started = how.start(self.decoder.borrow_mut(), &mut header);
470 let used = before - header.len();
471 self.input.consume(used);
472 match started {
473 Ok(()) => return Ok(true),
474 Err(e) => match skippable_frame_length(&e) {
475 Some(length) => self.input.skip_left = length,
476 None => return Err(frame_error(e)),
477 },
478 }
479 }
480 }
481}
482
483/// `inner` with one byte already taken from it put back in front, so a frame
484/// boundary can be probed for the end of the stream without losing the byte.
485struct Prefixed<'a, R: Read> {
486 first: Option<u8>,
487 inner: &'a mut R,
488}
489
490impl<R: Read> Read for Prefixed<'_, R> {
491 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
492 match (self.first.take(), buf.first_mut()) {
493 (Some(byte), Some(slot)) => {
494 *slot = byte;
495 Ok(1)
496 }
497 (byte, _) => {
498 self.first = byte;
499 self.inner.read(buf)
500 }
501 }
502 }
503}
504
505/// The length of the skippable frame (RFC 8878 3.1.2) whose header `e`
506/// reports, if it is one.
507fn skippable_frame_length(e: &FrameDecoderError) -> Option<u32> {
508 match e {
509 FrameDecoderError::ReadFrameHeaderError(ReadFrameHeaderError::SkipFrame {
510 length, ..
511 }) => Some(*length),
512 _ => None,
513 }
514}
515
516/// Read past a skippable frame's `length` content bytes.
517fn skip_frame_content<R: Read>(source: &mut R, length: u32) -> Result<(), FrameDecoderError> {
518 // Counted in the wire's `u32`: a `usize` is 16 bits on some targets, and a
519 // truncated count would leave part of the content to be read as a header.
520 let mut left = length;
521 if left == 0 {
522 return Ok(());
523 }
524 // Read in `SKIP_CHUNK`s, as skippable frames after the first frame are,
525 // on the heap and only as large as the content: a stack array that size
526 // would cost a no_std target 8 KiB of stack for every constructor call.
527 let mut scratch = alloc::vec![0u8; left.min(SKIP_CHUNK) as usize];
528 while left > 0 {
529 // The minimum is taken in `u32`, then fits `usize` as at most
530 // `SKIP_CHUNK`.
531 let take = left.min(scratch.len() as u32) as usize;
532 match source.read(&mut scratch[..take]) {
533 Ok(0) => return Err(FrameDecoderError::FailedToSkipFrame),
534 // `n <= take <= left`, so it fits the `u32` it is taken from.
535 Ok(n) => left -= n as u32,
536 Err(e) if e.kind() == crate::io::ErrorKind::Interrupted => {}
537 // A source that fails is not a frame cut short: its error is kept.
538 Err(e) => return Err(FrameDecoderError::FailedToReadSkippableFrame(e)),
539 }
540 }
541 Ok(())
542}
543
544/// How a frame's decoder is initialised.
545enum FrameStart<'d> {
546 /// Dictionaries resolved by the frame's dictionary id.
547 Plain,
548 /// The supplied dictionary, applied whatever the frame header names.
549 Dictionary(&'d DictionaryHandle),
550 /// The dictionary the decoder already holds, applied the same way.
551 HeldDictionary,
552}
553
554impl FrameStart<'_> {
555 fn start(
556 &self,
557 decoder: &mut FrameDecoder,
558 source: impl Read,
559 ) -> Result<(), FrameDecoderError> {
560 match self {
561 Self::Plain => decoder.init(source),
562 Self::Dictionary(dict) => decoder.init_with_dict_handle(source, dict),
563 Self::HeldDictionary => decoder.reset_with_active_dict(source),
564 }
565 }
566}
567
568/// Start the first content frame of `source`, skipping skippable frames in
569/// front of it. `false` when the source held only skippable frames, which
570/// decode to nothing; an empty source is an error from the header read.
571fn start_first_frame<R: Read>(
572 decoder: &mut FrameDecoder,
573 source: &mut R,
574 how: FrameStart<'_>,
575) -> Result<bool, FrameDecoderError> {
576 let mut started = how.start(decoder, &mut *source);
577 loop {
578 let length = match started {
579 Ok(()) => return Ok(true),
580 Err(e) => skippable_frame_length(&e).ok_or(e)?,
581 };
582 skip_frame_content(source, length)?;
583 let mut probe = [0u8; 1];
584 let n = read_at_boundary(source, &mut probe).map_err(|e| {
585 FrameDecoderError::ReadFrameHeaderError(ReadFrameHeaderError::MagicNumberReadError(e))
586 })?;
587 if n == 0 {
588 return Ok(false);
589 }
590 started = how.start(
591 decoder,
592 Prefixed {
593 first: Some(probe[0]),
594 inner: source,
595 },
596 );
597 }
598}
599
600/// One byte from `source` at a frame boundary, retried on interruption; `0`
601/// is the clean end of the stream.
602fn read_at_boundary<R: Read>(source: &mut R, probe: &mut [u8; 1]) -> Result<usize, Error> {
603 loop {
604 match source.read(probe) {
605 Err(e) if e.kind() == crate::io::ErrorKind::Interrupted => {}
606 other => return other,
607 }
608 }
609}
610
611/// Close a Raw block whose content is all in the decode buffer, recording its
612/// digest when per-block checksums are on.
613fn finish_raw_block(decoder: &mut FrameDecoder, raw: RawBlock) {
614 #[cfg(all(feature = "lsm", feature = "hash"))]
615 if let Some(digest) = raw.digest {
616 decoder.record_block_checksum(core::hash::Hasher::finish(&digest) as u32);
617 }
618 decoder.finish_raw_block(raw.size, raw.last);
619}
620
621/// A frame decode error as the `Read` error it surfaces through.
622fn frame_error(e: FrameDecoderError) -> Error {
623 #[cfg(feature = "std")]
624 return Error::other(e);
625 #[cfg(not(feature = "std"))]
626 return Error::new(ErrorKind::Other, alloc::boxed::Box::new(e));
627}
628
629/// The checks a frame can only pass once it is fully decoded and drained: the
630/// declared content size, then the content checksum in `Verify` mode.
631fn verify_finished_frame(decoder: &FrameDecoder) -> Result<(), Error> {
632 decoder.verify_content_size().map_err(frame_error)?;
633 #[cfg(feature = "hash")]
634 decoder.verify_content_checksum().map_err(frame_error)?;
635 Ok(())
636}
637
638impl<READ: Read, DEC: BorrowMut<FrameDecoder>> Read for StreamingDecoder<READ, DEC> {
639 /// Decode the stream into `buf`, frame after frame (RFC 8878 3: a stream
640 /// is one or more frames), as upstream zstd's `ZSTD_decompressStream`
641 /// does. Skippable frames are skipped; the source ending at a frame
642 /// boundary is the end of the stream, anything else is an error.
643 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
644 if buf.is_empty() || self.exhausted {
645 return Ok(0);
646 }
647 let mut written = 0;
648 loop {
649 let decoder = self.decoder.borrow_mut();
650 if decoder.is_finished() && decoder.can_collect() == 0 {
651 // Bytes in hand go back first: the frame's checks and the next
652 // frame's header wait for a call that has nothing to deliver,
653 // so an error never follows delivered bytes (the `Read`
654 // contract) and a source that has not sent the next frame
655 // yet is not waited on.
656 if written > 0 {
657 return Ok(written);
658 }
659 // Fully decoded and drained: the frame's length and running
660 // digest are final, so a frame shorter or longer than it
661 // declared, or with a bad checksum in `Verify` mode, fails here.
662 verify_finished_frame(decoder)?;
663 if !self.start_next_frame()? {
664 self.exhausted = true;
665 return Ok(0);
666 }
667 continue;
668 }
669 // A full `buf` never strands a checksum: a frame's last window of
670 // output is collectable only once the frame is finished, its
671 // checksum read, so the source already stands past the frame.
672 if written == buf.len() {
673 return Ok(written);
674 }
675 // A Raw block in progress reads on into the decode buffer once
676 // the output already there has been handed over.
677 if self.input.raw.is_some() && decoder.can_collect() == 0 {
678 // Return what this call has rather than wait on the source.
679 if written > 0 {
680 return Ok(written);
681 }
682 // The block stays recorded until the read has delivered: a
683 // `WouldBlock` returns here with the block still open.
684 let left = self.input.raw.as_ref().map_or(0, |raw| raw.left);
685 let n = self.input.read_raw(&mut self.source, left)?;
686 let mut raw = self.input.raw.take().expect("checked just above");
687 if n == 0 {
688 return Err(frame_error(decoder.raw_block_cut_short(raw.size, raw.last)));
689 }
690 let content = &self.input.buf[..n];
691 decoder.raw_block_push(content);
692 #[cfg(all(feature = "lsm", feature = "hash"))]
693 if let Some(digest) = raw.digest.as_mut() {
694 core::hash::Hasher::write(digest, content);
695 }
696 // `n <= left`, so it fits the `u32` it is taken from.
697 raw.left -= n as u32;
698 if raw.left == 0 {
699 finish_raw_block(decoder, raw);
700 } else {
701 self.input.raw = Some(raw);
702 }
703 continue;
704 }
705 // Otherwise the decoder is entered only with its next step whole,
706 // or with output to hand over: entering it with part of a block
707 // only parses the block header to find the block incomplete.
708 let want = decoder.input_needed(self.input.pending());
709 if self.input.raw.is_none()
710 && want > self.input.pending().len()
711 && decoder.can_collect() == 0
712 {
713 // Return what this call has rather than wait on the source.
714 if written > 0 {
715 return Ok(written);
716 }
717 // A Raw block's header alone is in hand: its content goes
718 // straight to the decode buffer from here on.
719 if let Some(&header) = self.input.pending().first_chunk::<3>()
720 && self.input.pending().len() == 3
721 && let Some((size, last)) = decoder
722 .start_raw_block(&header, true)
723 .map_err(frame_error)?
724 {
725 self.input.consume(3);
726 let raw = RawBlock {
727 size,
728 left: size,
729 last,
730 #[cfg(all(feature = "lsm", feature = "hash"))]
731 digest: decoder
732 .per_block_checksums_enabled()
733 .then(|| twox_hash::XxHash64::with_seed(0)),
734 };
735 if size == 0 {
736 finish_raw_block(decoder, raw);
737 } else {
738 self.input.raw = Some(raw);
739 }
740 continue;
741 }
742 if self.input.fill(&mut self.source, want)? == 0 {
743 return Err(self.cut_short());
744 }
745 continue;
746 }
747 // Decode the step, handing output to `buf` block by block: the
748 // decode window stays one window plus one block, as upstream's
749 // flush loop keeps it. The buffer takes the whole window at the
750 // first block whatever the frame declares, as upstream sizes a
751 // stream's buffer from the window.
752 let (consumed, produced) = decoder
753 .decode_available(self.input.pending(), &mut buf[written..], true)
754 .map_err(frame_error)?;
755 self.input.consume(consumed);
756 written += produced;
757 if consumed > 0 || produced > 0 {
758 continue;
759 }
760 if written > 0 {
761 return Ok(written);
762 }
763 // A step whose input is all here yet decodes nothing (a block over
764 // the frame's maximum, say) is a damaged frame: report it.
765 return Err(self.cut_short());
766 }
767 }
768
769 /// Decode-in-place fast path for whole-frame consumption. Instead of the
770 /// generic `read` loop (decode block -> `RingBuffer` -> copy into the
771 /// caller buffer), buffer the (compressed, hence small) source and decode
772 /// STRAIGHT into `output`'s spare capacity via the single-copy direct path,
773 /// pre-sized from the frame's declared content size. Only taken when the
774 /// decoder is at a frame boundary (nothing partially decoded / undrained);
775 /// otherwise it falls back to the generic grow-and-`read` loop so a caller
776 /// that mixed `read` with `read_to_end` still gets correct output.
777 ///
778 /// Per the `Read::read_to_end` contract this consumes the source to EOF: if
779 /// the stream holds several concatenated frames they are ALL decoded (and
780 /// skippable frames skipped), as with `read`.
781 #[cfg(feature = "std")]
782 fn read_to_end(&mut self, output: &mut alloc::vec::Vec<u8>) -> Result<usize, Error> {
783 let start_total = output.len();
784 if self.exhausted {
785 return Ok(0);
786 }
787 // `new()` already read the frame header, so the fast path applies when
788 // the decoder sits at the start of that frame with nothing decoded yet;
789 // a first Raw block part-read into the decode buffer is not that.
790 let at_start = self.input.raw.is_none() && {
791 let d = self.decoder.borrow_mut();
792 d.is_at_frame_start() && d.can_collect() == 0
793 };
794 // A forced dictionary is the one the decoder already holds; following
795 // frames are re-initialised with it in place, touching no reference
796 // count.
797 let keep_dictionary = self.forced_dictionary;
798 if at_start {
799 self.input.read_rest(&mut self.source)?;
800 let decoded = self.decoder.borrow_mut().decode_current_frame_to_vec(
801 self.input.pending(),
802 output,
803 keep_dictionary,
804 );
805 self.input.release();
806 decoded.map_err(Error::other)?;
807 return Ok(output.len() - start_total);
808 }
809 // Mid-frame fallback: drain through the generic path, which carries on
810 // into the following frames, so the source is consumed to true EOF.
811 loop {
812 let start = output.len();
813 output.resize(start + MAX_BLOCK_SIZE as usize, 0);
814 // On error, drop the just-grown (zeroed) tail before propagating so
815 // the caller never observes bytes that were never decoded.
816 let n = match self.read(&mut output[start..]) {
817 Ok(n) => n,
818 Err(e) => {
819 output.truncate(start);
820 return Err(e);
821 }
822 };
823 output.truncate(start + n);
824 if n == 0 {
825 break;
826 }
827 }
828 Ok(output.len() - start_total)
829 }
830
831 /// no_std counterpart of the decode-in-place `read_to_end` fast path above
832 /// (the no_std `Read::read_to_end` returns `()` instead of the byte count).
833 #[cfg(not(feature = "std"))]
834 fn read_to_end(&mut self, output: &mut alloc::vec::Vec<u8>) -> Result<(), Error> {
835 if self.exhausted {
836 return Ok(());
837 }
838 let at_start = self.input.raw.is_none() && {
839 let d = self.decoder.borrow_mut();
840 d.is_at_frame_start() && d.can_collect() == 0
841 };
842 // As in the std path: the decoder's own dictionary, reused in place.
843 let keep_dictionary = self.forced_dictionary;
844 if at_start {
845 self.input.read_rest(&mut self.source)?;
846 let decoded = self.decoder.borrow_mut().decode_current_frame_to_vec(
847 self.input.pending(),
848 output,
849 keep_dictionary,
850 );
851 self.input.release();
852 decoded.map_err(|e| Error::new(ErrorKind::Other, alloc::boxed::Box::new(e)))?;
853 return Ok(());
854 }
855 // Mid-frame fallback: drain through the generic path, which carries on
856 // into the following frames, so the source is consumed to true EOF.
857 loop {
858 let start = output.len();
859 output.resize(start + MAX_BLOCK_SIZE as usize, 0);
860 // On error, drop the just-grown (zeroed) tail before propagating so
861 // the caller never observes bytes that were never decoded.
862 let n = match self.read(&mut output[start..]) {
863 Ok(n) => n,
864 Err(e) => {
865 output.truncate(start);
866 return Err(e);
867 }
868 };
869 output.truncate(start + n);
870 if n == 0 {
871 break;
872 }
873 }
874 Ok(())
875 }
876}
877
878#[cfg(test)]
879mod tests;