diff --git a/src/bin/zstd.rs b/src/bin/zstd.rs index 1006179..af5760f 100644 --- a/src/bin/zstd.rs +++ b/src/bin/zstd.rs @@ -62,10 +62,10 @@ fn main() { while tracker.file_pos < tracker.file_size { match frame_dec.reset(&mut f) { - Err(FrameDecoderError::ReadFrameHeaderError(ReadFrameHeaderError::SkipFrame( - magic_num, - skip_size, - ))) => { + Err(FrameDecoderError::ReadFrameHeaderError(ReadFrameHeaderError::SkipFrame { + magic_number: magic_num, + length: skip_size, + })) => { eprintln!("Found a skippable frame with magic number: {magic_num} and size: {skip_size}"); tracker.file_pos = f.stream_position().unwrap(); tracker.file_pos += skip_size as u64; diff --git a/src/frame.rs b/src/frame.rs index 0f77176..eabfca5 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -154,8 +154,10 @@ pub enum ReadFrameHeaderError { DictionaryIdReadError(Error), #[display(fmt = "Error while reading frame content size: {_0}")] FrameContentSizeReadError(Error), - #[display(fmt = "SkippableFrame encountered with MagicNumber 0x{_0:X} and length {_1} bytes")] - SkipFrame(u32, u32), + #[display( + fmt = "SkippableFrame encountered with MagicNumber 0x{magic_number:X} and length {length} bytes" + )] + SkipFrame { magic_number: u32, length: u32 }, } pub fn read_frame_header(mut r: impl Read) -> Result<(Frame, u8), ReadFrameHeaderError> { @@ -171,7 +173,10 @@ pub fn read_frame_header(mut r: impl Read) -> Result<(Frame, u8), ReadFrameHeade r.read_exact(&mut buf) .map_err(err::FrameDescriptorReadError)?; let skip_size = u32::from_le_bytes(buf); - return Err(ReadFrameHeaderError::SkipFrame(magic_num, skip_size)); + return Err(ReadFrameHeaderError::SkipFrame { + magic_number: magic_num, + length: skip_size, + }); } if magic_num != MAGIC_NUM { diff --git a/src/streaming_decoder.rs b/src/streaming_decoder.rs index 52aa10c..3021e3f 100644 --- a/src/streaming_decoder.rs +++ b/src/streaming_decoder.rs @@ -8,6 +8,14 @@ use crate::io::{Error, ErrorKind, Read}; /// /// The lower level FrameDecoder by comparison allows for finer grained control but need sto have it's decode_blocks method called continously /// to decode the zstd-frame. +/// +/// ## Caveat +/// [StreamingDecoder] expects the underlying stream to only contain a single frame. +/// To decode all the frames in a finite stream, the calling code needs to recreate +/// the instance of the decoder +/// and handle +/// [crate::frame::ReadFrameHeaderError::SkipFrame] +/// errors by skipping forward the `length` amount of bytes, see pub struct StreamingDecoder> { pub decoder: DEC, source: READ, diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 78dbab1..3cbcd23 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -55,7 +55,10 @@ fn skippable_frame() { let err = frame::read_frame_header(content.as_slice()); assert!(matches!( err, - Err(frame::ReadFrameHeaderError::SkipFrame(0x184D2A50u32, 300)) + Err(frame::ReadFrameHeaderError::SkipFrame { + magic_number: 0x184D2A50u32, + length: 300 + }) )); content.clear(); @@ -65,10 +68,10 @@ fn skippable_frame() { let err = frame::read_frame_header(content.as_slice()); assert!(matches!( err, - Err(frame::ReadFrameHeaderError::SkipFrame( - 0x184D2A5Fu32, - 0xFFFFFFFF - )) + Err(frame::ReadFrameHeaderError::SkipFrame { + magic_number: 0x184D2A5Fu32, + length: 0xFFFFFFFF + }) )); }