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