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 return 4;
320 }
321 4
322 };
323 let Some(&descriptor) = bytes.get(descriptor_at) else {
324 return descriptor_at + 1;
325 };
326 descriptor_at + crate::decoding::frame::FrameDescriptor(descriptor).header_len()
327}
328
329impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
330 /// [`new`](StreamingDecoder::new) driving a caller-supplied
331 /// [`FrameDecoder`], so its buffers and settings (magicless format,
332 /// registered dictionaries, checksum mode) carry over from stream to
333 /// stream. Nothing is read from `source` until the first read.
334 ///
335 /// # Examples
336 /// ```
337 /// use std::io::Read;
338 /// use structured_zstd::decoding::{FrameDecoder, StreamingDecoder};
339 /// use structured_zstd::encoding::{CompressionLevel, compress_to_vec};
340 ///
341 /// let frame = compress_to_vec(&b"reused decoder"[..], CompressionLevel::Fastest);
342 /// let mut decoder = FrameDecoder::new();
343 /// for _ in 0..2 {
344 /// let mut stream = StreamingDecoder::new_with_decoder(&frame[..], &mut decoder);
345 /// let mut decoded = Vec::new();
346 /// stream.read_to_end(&mut decoded).unwrap();
347 /// assert_eq!(decoded, b"reused decoder");
348 /// }
349 /// ```
350 pub fn new_with_decoder(source: READ, decoder: DEC) -> StreamingDecoder<READ, DEC> {
351 StreamingDecoder {
352 decoder,
353 source,
354 forced_dictionary: false,
355 position: Position::BeforeFirstFrame,
356 input: Input::new(),
357 }
358 }
359
360 /// [`new_with_decoder`](Self::new_with_decoder) with `dict` applied to
361 /// every frame even when its header omits the dictionary ID, as
362 /// [`new_with_dictionary_handle`](StreamingDecoder::new_with_dictionary_handle)
363 /// applies it (same warning). A decoder reused frame after frame keeps its
364 /// buffers and, for the same dictionary, the handle it already holds, so
365 /// after the first frame it allocates nothing and touches no reference
366 /// count.
367 ///
368 /// # Errors
369 ///
370 /// Only for a dictionary whose content no frame can use, as a
371 /// [`DictionaryRefused`] that hands back `source`, unread, and `decoder`
372 /// as they were given. Nothing is read from `source` until the first
373 /// read, which reports a frame that does not match the dictionary.
374 ///
375 /// # Examples
376 /// ```
377 /// use std::io::Read;
378 /// use structured_zstd::decoding::{Dictionary, DictionaryHandle, FrameDecoder, StreamingDecoder};
379 /// use structured_zstd::encoding::{FrameCompressor, CompressionLevel};
380 ///
381 /// let content = b"a dictionary of words the frames reuse".to_vec();
382 /// let dictionary = DictionaryHandle::from_dictionary(
383 /// Dictionary::from_raw_content(1, content.clone()).unwrap(),
384 /// );
385 /// let mut compressor: FrameCompressor = FrameCompressor::new(CompressionLevel::Default);
386 /// compressor.set_dictionary(Dictionary::from_raw_content(1, content).unwrap()).unwrap();
387 /// let frame = compressor.compress_independent_frame(b"the frames reuse words");
388 ///
389 /// let mut decoder = FrameDecoder::new();
390 /// for _ in 0..2 {
391 /// let mut stream =
392 /// StreamingDecoder::new_with_decoder_and_dictionary_handle(&frame[..], &mut decoder, &dictionary)
393 /// .unwrap();
394 /// let mut decoded = Vec::new();
395 /// stream.read_to_end(&mut decoded).unwrap();
396 /// assert_eq!(decoded, b"the frames reuse words");
397 /// }
398 ///
399 /// // A dictionary no frame can use is refused, and the decoder and the
400 /// // frame come back to be used another way.
401 /// let mut unusable = Dictionary::from_raw_content(1, b"content".to_vec()).unwrap();
402 /// unusable.offset_hist[0] = 0;
403 /// let unusable = DictionaryHandle::from_dictionary(unusable);
404 /// let (source, decoder, _error) =
405 /// StreamingDecoder::new_with_decoder_and_dictionary_handle(&frame[..], decoder, &unusable)
406 /// .err()
407 /// .expect("a zero repeat offset is refused")
408 /// .into_parts();
409 /// assert_eq!(source, &frame[..]);
410 /// # let _: FrameDecoder = decoder;
411 /// ```
412 pub fn new_with_decoder_and_dictionary_handle(
413 source: READ,
414 mut decoder: DEC,
415 dict: &DictionaryHandle,
416 ) -> Result<StreamingDecoder<READ, DEC>, DictionaryRefused<READ, DEC>> {
417 // A refused dictionary leaves the decoder as it was.
418 if let Err(error) = decoder.borrow_mut().arm_dict(dict) {
419 return Err(DictionaryRefused {
420 source,
421 decoder,
422 error,
423 });
424 }
425 Ok(StreamingDecoder {
426 decoder,
427 source,
428 forced_dictionary: true,
429 position: Position::BeforeFirstFrame,
430 input: Input::new(),
431 })
432 }
433}
434
435impl<READ: Read> StreamingDecoder<READ, FrameDecoder> {
436 /// Create a streaming decoder over `source`.
437 ///
438 /// Nothing is read from `source` here: the first frame's header is read by
439 /// the first `read` or `read_to_end`, which is where a source that is not
440 /// a zstd stream, or is empty, reports its error. Until then
441 /// [`into_inner`](Self::into_inner) hands `source` back untouched, and
442 /// after such an error it hands back whatever the source holds past the
443 /// bytes the decoder took.
444 ///
445 /// # Examples
446 /// ```
447 /// use std::io::Read;
448 /// use structured_zstd::decoding::StreamingDecoder;
449 ///
450 /// let mut decoder = StreamingDecoder::new(&b"not a zstd frame"[..]);
451 /// let mut out = Vec::new();
452 /// assert!(decoder.read_to_end(&mut out).is_err());
453 /// ```
454 pub fn new(source: READ) -> StreamingDecoder<READ, FrameDecoder> {
455 StreamingDecoder::new_with_decoder(source, FrameDecoder::new())
456 }
457
458 /// Create a streaming decoder using a pre-parsed dictionary handle.
459 ///
460 /// Nothing is read from `source` here, as with [`new`](Self::new).
461 ///
462 /// # Errors
463 ///
464 /// Only for a dictionary whose content no frame can use, as a
465 /// [`DictionaryRefused`] that hands `source` back unread.
466 ///
467 /// # Warning
468 ///
469 /// This constructor initializes the underlying [`FrameDecoder`] with
470 /// `dict`, even if a frame header omits the optional dictionary ID.
471 /// Callers must only use it when they already know the stream was encoded
472 /// with this dictionary; otherwise decoded output can be silently
473 /// corrupted.
474 pub fn new_with_dictionary_handle(
475 source: READ,
476 dict: &DictionaryHandle,
477 ) -> Result<StreamingDecoder<READ, FrameDecoder>, DictionaryRefused<READ>> {
478 Self::new_with_decoder_and_dictionary_handle(source, FrameDecoder::new(), dict).map_err(
479 // The decoder was made here, so only the source goes back.
480 |refused| DictionaryRefused {
481 source: refused.source,
482 decoder: (),
483 error: refused.error,
484 },
485 )
486 }
487
488 /// Create a streaming decoder using a serialized dictionary blob.
489 ///
490 /// # Errors
491 ///
492 /// A blob that is not a dictionary, or one no frame can use, as a
493 /// [`DictionaryRefused`] that hands `source` back unread.
494 ///
495 /// # Warning
496 ///
497 /// This API forwards to [`StreamingDecoder::new_with_dictionary_handle`]
498 /// and therefore applies the decoded dictionary to frames whose headers may
499 /// omit the optional dictionary ID. Only use it when the stream is known to
500 /// be encoded with that dictionary.
501 pub fn new_with_dictionary_bytes(
502 source: READ,
503 raw_dictionary: &[u8],
504 ) -> Result<StreamingDecoder<READ, FrameDecoder>, DictionaryRefused<READ>> {
505 match DictionaryHandle::decode_dict(raw_dictionary) {
506 Ok(dict) => Self::new_with_dictionary_handle(source, &dict),
507 Err(error) => Err(DictionaryRefused {
508 source,
509 decoder: (),
510 error: FrameDecoderError::from(error),
511 }),
512 }
513 }
514}
515
516impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
517 /// Gets a reference to the underlying reader.
518 pub fn get_ref(&self) -> &READ {
519 &self.source
520 }
521
522 /// Gets a mutable reference to the underlying reader.
523 ///
524 /// It is inadvisable to directly read from the underlying reader.
525 pub fn get_mut(&mut self) -> &mut READ {
526 &mut self.source
527 }
528
529 /// Gets a mutable reference to the frame decoder driving this stream.
530 ///
531 /// Exposed for settings that are read as decoding proceeds rather than at
532 /// construction — [`FrameDecoder::set_content_checksum`] above all, which a
533 /// caller that wants mismatches to fail (rather than merely be computed)
534 /// has to reach after the constructor has chosen the decoder, including
535 /// on the dictionary paths.
536 pub fn decoder_mut(&mut self) -> &mut FrameDecoder {
537 self.decoder.borrow_mut()
538 }
539
540 /// Destructures this object into the inner reader.
541 ///
542 /// This reads nothing. A decoder that was never read hands the reader back
543 /// untouched. The decoder reads only what its next step needs, so once a
544 /// frame's content has been delivered the reader stands right after that
545 /// frame. Bytes of a step a `WouldBlock` left unfinished stay with the
546 /// decoder.
547 ///
548 /// # Examples
549 /// ```
550 /// use structured_zstd::decoding::StreamingDecoder;
551 ///
552 /// let data = b"\x28\xb5\x2f\xfd and whatever follows";
553 /// let decoder = StreamingDecoder::new(&data[..]);
554 /// assert_eq!(decoder.into_inner(), &data[..]);
555 /// ```
556 pub fn into_inner(self) -> READ
557 where
558 READ: Sized,
559 {
560 self.source
561 }
562
563 /// Destructures this object into both the inner reader and [FrameDecoder].
564 pub fn into_parts(self) -> (READ, DEC)
565 where
566 READ: Sized,
567 {
568 (self.source, self.decoder)
569 }
570
571 /// Destructures this object into the inner [FrameDecoder].
572 pub fn into_frame_decoder(self) -> DEC {
573 self.decoder
574 }
575
576 /// The error for a source that ended inside a frame. Cut inside the
577 /// trailing checksum, that is what it reports; cut inside a block, the
578 /// leftover input goes to the block decoder, which reports how it was cut
579 /// short as it does for any truncated frame. Whole input never reaches
580 /// here (it would have decoded), so that decode fails; were it to pass,
581 /// the cut is still reported, as an early end of input.
582 fn cut_short(&mut self) -> Error {
583 let decoder = self.decoder.borrow_mut();
584 if decoder.awaits_checksum() {
585 return frame_error(FrameDecoderError::FailedToReadChecksum(Error::from(
586 ErrorKind::UnexpectedEof,
587 )));
588 }
589 let mut rest = self.input.pending();
590 decoder
591 .decode_blocks(&mut rest, BlockDecodingStrategy::All)
592 .map_or_else(frame_error, |_| Error::from(ErrorKind::UnexpectedEof))
593 }
594
595 /// Start the next frame of the stream, the first included, skipping
596 /// skippable frames, with the constructor's dictionary if it had one.
597 /// `false` when the source ends cleanly at a frame boundary, which the
598 /// start of the stream is not; anything else that is not a frame is an
599 /// error.
600 ///
601 /// The source's own errors go back as it reported them, so a non-blocking
602 /// source's `WouldBlock` stays one; what the boundary had read stays in
603 /// [`Input`], and the header is parsed only once it is whole, so a retry
604 /// resumes where the source stopped.
605 fn start_frame(&mut self) -> Result<bool, Error> {
606 let how = if self.forced_dictionary {
607 FrameStart::HeldDictionary
608 } else {
609 FrameStart::Plain
610 };
611 let magicless = self.decoder.borrow_mut().is_magicless();
612 loop {
613 while self.input.skip_left > 0 {
614 // Counted in the wire's `u32`; a step is at most `SKIP_CHUNK`,
615 // which every `usize` holds.
616 let step = self.input.skip_left.min(SKIP_CHUNK);
617 if self.input.pending().is_empty()
618 && self.input.fill(&mut self.source, step as usize)? == 0
619 {
620 return Err(frame_error(FrameDecoderError::FailedToSkipFrame));
621 }
622 // Reads stop at `step`, so what is pending is skippable content;
623 // the minimum is taken in `u32`, the wire's width.
624 let pending = u32::try_from(self.input.pending().len()).unwrap_or(u32::MAX);
625 let take = self.input.skip_left.min(pending);
626 self.input.consume(take as usize);
627 self.input.skip_left -= take;
628 }
629 loop {
630 let have = self.input.pending().len();
631 let want = header_len(self.input.pending(), magicless);
632 if have >= want {
633 break;
634 }
635 if self.input.fill(&mut self.source, want)? == 0 {
636 if have == 0 {
637 if self.position == Position::BeforeFirstFrame {
638 return Err(no_frame_error());
639 }
640 return Ok(false);
641 }
642 // The source ended inside a header: let the parser report
643 // it as it reports any header cut short.
644 break;
645 }
646 }
647 let mut header = self.input.pending();
648 let before = header.len();
649 let started = how.start(self.decoder.borrow_mut(), &mut header);
650 let used = before - header.len();
651 self.input.consume(used);
652 match started {
653 Ok(()) => {
654 self.position = Position::InFrame;
655 return Ok(true);
656 }
657 Err(e) => match skippable_frame_length(&e) {
658 Some(length) => {
659 // A stream of skippable frames alone is a stream that
660 // holds no content, not an empty one.
661 self.position = Position::BetweenFrames;
662 self.input.skip_left = length;
663 }
664 None => return Err(frame_error(e)),
665 },
666 }
667 }
668 }
669}
670
671/// The length of the skippable frame (RFC 8878 3.1.2) whose header `e`
672/// reports, if it is one.
673fn skippable_frame_length(e: &FrameDecoderError) -> Option<u32> {
674 match e {
675 FrameDecoderError::ReadFrameHeaderError(ReadFrameHeaderError::SkipFrame {
676 length, ..
677 }) => Some(*length),
678 _ => None,
679 }
680}
681
682/// How a frame's decoder is initialised.
683enum FrameStart {
684 /// Dictionaries resolved by the frame's dictionary id.
685 Plain,
686 /// The dictionary the decoder holds, applied whatever the frame header
687 /// names.
688 HeldDictionary,
689}
690
691impl FrameStart {
692 fn start(
693 &self,
694 decoder: &mut FrameDecoder,
695 source: impl Read,
696 ) -> Result<(), FrameDecoderError> {
697 match self {
698 Self::Plain => decoder.init(source),
699 Self::HeldDictionary => decoder.reset_with_active_dict(source),
700 }
701 }
702}
703
704/// Close a Raw block whose content is all in the decode buffer, recording its
705/// digest when per-block checksums are on.
706fn finish_raw_block(decoder: &mut FrameDecoder, raw: RawBlock) {
707 #[cfg(all(feature = "lsm", feature = "hash"))]
708 if let Some(digest) = raw.digest {
709 decoder.record_block_checksum(core::hash::Hasher::finish(&digest) as u32);
710 }
711 decoder.finish_raw_block(raw.size, raw.last);
712}
713
714/// A frame decode error as the `Read` error it surfaces through.
715fn frame_error(e: FrameDecoderError) -> Error {
716 #[cfg(feature = "std")]
717 return Error::other(e);
718 #[cfg(not(feature = "std"))]
719 return Error::new(ErrorKind::Other, alloc::boxed::Box::new(e));
720}
721
722/// The error for a source that ends before its first frame begins: there is no
723/// magic number to read, as there is for any frame header cut short there.
724fn no_frame_error() -> Error {
725 frame_error(FrameDecoderError::ReadFrameHeaderError(
726 ReadFrameHeaderError::MagicNumberReadError(Error::from(ErrorKind::UnexpectedEof)),
727 ))
728}
729
730/// The checks a frame can only pass once it is fully decoded and drained: the
731/// declared content size, then the content checksum in `Verify` mode.
732fn verify_finished_frame(decoder: &FrameDecoder) -> Result<(), Error> {
733 decoder.verify_content_size().map_err(frame_error)?;
734 #[cfg(feature = "hash")]
735 decoder.verify_content_checksum().map_err(frame_error)?;
736 Ok(())
737}
738
739impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
740 /// [`read`](Read::read), handing `finished` each frame the call finishes,
741 /// at the moment it is verified and before the next frame is started, as
742 /// upstream's `ZSTD_trace_decompress_end` hook is called. One call can
743 /// finish several frames (empty frames deliver nothing, so it passes on
744 /// to the next), and each is reported in stream order; skippable frames
745 /// are not. `read_to_end` reports none.
746 ///
747 /// # Examples
748 /// ```
749 /// use structured_zstd::decoding::StreamingDecoder;
750 /// use structured_zstd::encoding::{CompressionLevel, compress_to_vec};
751 ///
752 /// let frame = compress_to_vec(&b"one frame"[..], CompressionLevel::Fastest);
753 /// let mut decoder = StreamingDecoder::new(&frame[..]);
754 /// let mut buf = [0u8; 64];
755 /// let mut finished = Vec::new();
756 /// while decoder
757 /// .read_reporting_frames(&mut buf, |frame| finished.push(frame))
758 /// .unwrap()
759 /// > 0
760 /// {}
761 /// assert_eq!(finished.len(), 1);
762 /// assert_eq!(finished[0].compressed_size, frame.len() as u64);
763 /// assert_eq!(finished[0].decompressed_size, 9);
764 /// ```
765 pub fn read_reporting_frames(
766 &mut self,
767 buf: &mut [u8],
768 mut finished: impl FnMut(FinishedFrame),
769 ) -> Result<usize, Error> {
770 if buf.is_empty() || self.position == Position::End {
771 return Ok(0);
772 }
773 let mut written = 0;
774 loop {
775 if self.position != Position::InFrame {
776 // A call reaches a frame boundary with nothing delivered: a
777 // finished frame hands its last bytes back before it is left
778 // (the check below), so the next frame's header is read only
779 // by a call with nothing to deliver, an error never follows
780 // delivered bytes (the `Read` contract), and a source that has
781 // not sent the next frame yet is not waited on.
782 debug_assert_eq!(written, 0, "a frame boundary is reached empty-handed");
783 if !self.start_frame()? {
784 self.position = Position::End;
785 return Ok(0);
786 }
787 continue;
788 }
789 let decoder = self.decoder.borrow_mut();
790 if decoder.is_finished() && decoder.can_collect() == 0 {
791 // Bytes in hand go back first: the frame's checks and the
792 // next frame's header wait for a call with nothing to deliver.
793 if written > 0 {
794 return Ok(written);
795 }
796 // Fully decoded and drained: the frame's length and running
797 // digest are final, so a frame shorter or longer than it
798 // declared, or with a bad checksum in `Verify` mode, fails here.
799 verify_finished_frame(decoder)?;
800 finished(FinishedFrame {
801 compressed_size: decoder.bytes_read_from_source(),
802 decompressed_size: decoder.decoded_size(),
803 });
804 self.position = Position::BetweenFrames;
805 continue;
806 }
807 // A full `buf` never strands a checksum: a frame's last window of
808 // output is collectable only once the frame is finished, its
809 // checksum read, so the source already stands past the frame.
810 if written == buf.len() {
811 return Ok(written);
812 }
813 // A Raw block in progress reads on into the decode buffer once
814 // the output already there has been handed over.
815 if self.input.raw.is_some() && decoder.can_collect() == 0 {
816 // Return what this call has rather than wait on the source.
817 if written > 0 {
818 return Ok(written);
819 }
820 // A ceiling lowered while the block was open refuses the rest
821 // of it, as it refuses every other step of the frame.
822 decoder.check_window_still_admitted().map_err(frame_error)?;
823 // The block stays recorded until the read has delivered: a
824 // `WouldBlock` returns here with the block still open.
825 let left = self.input.raw.as_ref().map_or(0, |raw| raw.left);
826 let n = self.input.read_raw(&mut self.source, left)?;
827 let mut raw = self.input.raw.take().expect("checked just above");
828 if n == 0 {
829 return Err(frame_error(decoder.raw_block_cut_short(raw.size, raw.last)));
830 }
831 let content = &self.input.buf[..n];
832 decoder.raw_block_push(content);
833 #[cfg(all(feature = "lsm", feature = "hash"))]
834 if let Some(digest) = raw.digest.as_mut() {
835 core::hash::Hasher::write(digest, content);
836 }
837 // `n <= left`, so it fits the `u32` it is taken from.
838 raw.left -= n as u32;
839 if raw.left == 0 {
840 finish_raw_block(decoder, raw);
841 } else {
842 self.input.raw = Some(raw);
843 }
844 continue;
845 }
846 // Otherwise the decoder is entered only with its next step whole,
847 // or with output to hand over: entering it with part of a block
848 // only parses the block header to find the block incomplete.
849 let want = decoder.input_needed(self.input.pending());
850 if self.input.raw.is_none()
851 && want > self.input.pending().len()
852 && decoder.can_collect() == 0
853 {
854 // Return what this call has rather than wait on the source.
855 if written > 0 {
856 return Ok(written);
857 }
858 // A Raw block's header alone is in hand: its content goes
859 // straight to the decode buffer from here on.
860 if let Some(&header) = self.input.pending().first_chunk::<3>()
861 && self.input.pending().len() == 3
862 && let Some((size, last)) = decoder
863 .start_raw_block(&header, true)
864 .map_err(frame_error)?
865 {
866 self.input.consume(3);
867 let raw = RawBlock {
868 size,
869 left: size,
870 last,
871 #[cfg(all(feature = "lsm", feature = "hash"))]
872 digest: decoder
873 .per_block_checksums_enabled()
874 .then(|| twox_hash::XxHash64::with_seed(0)),
875 };
876 if size == 0 {
877 finish_raw_block(decoder, raw);
878 } else {
879 self.input.raw = Some(raw);
880 }
881 continue;
882 }
883 if self.input.fill(&mut self.source, want)? == 0 {
884 return Err(self.cut_short());
885 }
886 continue;
887 }
888 // Decode the step, handing output to `buf` block by block: the
889 // decode window stays one window plus one block, as upstream's
890 // flush loop keeps it. The buffer takes the whole window at the
891 // first block whatever the frame declares, as upstream sizes a
892 // stream's buffer from the window.
893 let (consumed, produced) = decoder
894 .decode_available(self.input.pending(), &mut buf[written..], true)
895 .map_err(frame_error)?;
896 self.input.consume(consumed);
897 written += produced;
898 if consumed > 0 || produced > 0 {
899 continue;
900 }
901 if written > 0 {
902 return Ok(written);
903 }
904 // A step whose input is all here yet decodes nothing (a block over
905 // the frame's maximum, say) is a damaged frame: report it.
906 return Err(self.cut_short());
907 }
908 }
909}
910
911impl<READ: Read, DEC: BorrowMut<FrameDecoder>> Read for StreamingDecoder<READ, DEC> {
912 /// Decode the stream into `buf`, frame after frame (RFC 8878 3: a stream
913 /// is one or more frames), as upstream zstd's `ZSTD_decompressStream`
914 /// does. Skippable frames are skipped; the source ending at a frame
915 /// boundary is the end of the stream, anything else is an error.
916 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
917 self.read_reporting_frames(buf, |_| {})
918 }
919
920 /// Decode-in-place fast path for whole-frame consumption. Instead of the
921 /// generic `read` loop (decode block -> `RingBuffer` -> copy into the
922 /// caller buffer), buffer the (compressed, hence small) source and decode
923 /// STRAIGHT into `output`'s spare capacity via the single-copy direct path,
924 /// pre-sized from the frame's declared content size. Only taken when the
925 /// decoder is at a frame boundary (nothing partially decoded / undrained);
926 /// otherwise it falls back to the generic grow-and-`read` loop so a caller
927 /// that mixed `read` with `read_to_end` still gets correct output.
928 ///
929 /// Per the `Read::read_to_end` contract this consumes the source to EOF: if
930 /// the stream holds several concatenated frames they are ALL decoded (and
931 /// skippable frames skipped), as with `read`.
932 #[cfg(feature = "std")]
933 fn read_to_end(&mut self, output: &mut alloc::vec::Vec<u8>) -> Result<usize, Error> {
934 let start_total = output.len();
935 self.decode_rest_to_vec(output)?;
936 Ok(output.len() - start_total)
937 }
938
939 /// no_std counterpart of the decode-in-place `read_to_end` above (the
940 /// no_std `Read::read_to_end` returns `()` instead of the byte count).
941 #[cfg(not(feature = "std"))]
942 fn read_to_end(&mut self, output: &mut alloc::vec::Vec<u8>) -> Result<(), Error> {
943 self.decode_rest_to_vec(output)
944 }
945}
946
947impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
948 /// Body of both `read_to_end`s: decode the rest of the stream, appending
949 /// to `output`.
950 fn decode_rest_to_vec(&mut self, output: &mut alloc::vec::Vec<u8>) -> Result<(), Error> {
951 // A forced dictionary is the one the decoder already holds; every
952 // frame is initialised with it in place, touching no reference count.
953 let keep_dictionary = self.forced_dictionary;
954 // The first header is read the bounded way, a step at a time, so a
955 // source that is not a zstd stream is refused after a header's worth
956 // of bytes instead of after the whole of it is gathered below.
957 if self.position == Position::BeforeFirstFrame && !self.start_frame()? {
958 self.position = Position::End;
959 }
960 match self.position {
961 Position::End => return Ok(()),
962 // A frame whose header is read, with nothing decoded yet; a first
963 // Raw block part-read into the decode buffer is not that.
964 Position::InFrame
965 if self.input.raw.is_none() && {
966 let d = self.decoder.borrow_mut();
967 d.is_at_frame_start() && d.can_collect() == 0
968 } =>
969 {
970 self.input.read_rest(&mut self.source)?;
971 let decoded = self.decoder.borrow_mut().decode_current_frame_to_vec(
972 self.input.pending(),
973 output,
974 keep_dictionary,
975 );
976 self.input.release();
977 decoded.map_err(frame_error)?;
978 self.position = Position::End;
979 return Ok(());
980 }
981 Position::BeforeFirstFrame | Position::InFrame | Position::BetweenFrames => {}
982 }
983 // Mid-frame fallback: drain through the generic path, which carries on
984 // into the following frames, so the source is consumed to true EOF.
985 loop {
986 let start = output.len();
987 output.resize(start + MAX_BLOCK_SIZE as usize, 0);
988 // On error, drop the just-grown (zeroed) tail before propagating so
989 // the caller never observes bytes that were never decoded.
990 let n = match self.read(&mut output[start..]) {
991 Ok(n) => n,
992 Err(e) => {
993 output.truncate(start);
994 return Err(e);
995 }
996 };
997 output.truncate(start + n);
998 if n == 0 {
999 return Ok(());
1000 }
1001 }
1002 }
1003}
1004
1005#[cfg(test)]
1006mod tests;