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/// ```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;