Skip to main content

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