lz4_flex/frame/
mod.rs

1//! LZ4 Frame Format
2//!
3//! As defined in <https://github.com/lz4/lz4/blob/dev/doc/lz4_Frame_format.md>
4//!
5//! # Example: compress data on `stdin` with frame format
6//! This program reads data from `stdin`, compresses it and emits it to `stdout`.
7//! This example can be found in `examples/compress.rs`:
8//! ```no_run
9//! use std::io;
10//! let stdin = io::stdin();
11//! let stdout = io::stdout();
12//! let mut rdr = stdin.lock();
13//! // Wrap the stdout writer in a LZ4 Frame writer.
14//! let mut wtr = lz4_flex::frame::FrameEncoder::new(stdout.lock());
15//! io::copy(&mut rdr, &mut wtr).expect("I/O operation failed");
16//! wtr.finish().unwrap();
17//! ```
18//!
19
20use std::{fmt, io};
21
22#[cfg_attr(feature = "safe-encode", forbid(unsafe_code))]
23pub(crate) mod compress;
24#[cfg_attr(feature = "safe-decode", forbid(unsafe_code))]
25pub(crate) mod decompress;
26pub(crate) mod header;
27
28pub use compress::{AutoFinishEncoder, FrameEncoder};
29pub use decompress::FrameDecoder;
30pub use header::{BlockMode, BlockSize, FrameInfo};
31
32#[derive(Debug)]
33#[non_exhaustive]
34/// Errors that can occur when de/compressing lz4.
35pub enum Error {
36    /// Compression error.
37    CompressionError(crate::block::CompressError),
38    /// Decompression error.
39    DecompressionError(crate::block::DecompressError),
40    /// An io::Error was encountered.
41    IoError(io::Error),
42    /// Unsupported block size.
43    UnsupportedBlocksize(u8),
44    /// Unsupported frame version.
45    UnsupportedVersion(u8),
46    /// Wrong magic number for the LZ4 frame format.
47    WrongMagicNumber,
48    /// Reserved bits set.
49    ReservedBitsSet,
50    /// Block header is malformed.
51    InvalidBlockInfo,
52    /// Read a block larger than specified in the Frame header.
53    BlockTooBig,
54    /// The Frame header checksum doesn't match.
55    HeaderChecksumError,
56    /// The block checksum doesn't match.
57    BlockChecksumError,
58    /// The content checksum doesn't match.
59    ContentChecksumError,
60    /// Read an skippable frame.
61    /// The caller may read the specified amount of bytes from the underlying io::Read.
62    SkippableFrame(u32),
63    /// External dictionaries are not supported.
64    DictionaryNotSupported,
65    /// Content length differs.
66    ContentLengthError {
67        /// Expected content length.
68        expected: u64,
69        /// Actual content lenght.
70        actual: u64,
71    },
72}
73
74impl From<Error> for io::Error {
75    fn from(e: Error) -> Self {
76        match e {
77            Error::IoError(e) => e,
78            Error::CompressionError(_)
79            | Error::DecompressionError(_)
80            | Error::SkippableFrame(_)
81            | Error::DictionaryNotSupported => io::Error::new(io::ErrorKind::Other, e),
82            Error::WrongMagicNumber
83            | Error::UnsupportedBlocksize(..)
84            | Error::UnsupportedVersion(..)
85            | Error::ReservedBitsSet
86            | Error::InvalidBlockInfo
87            | Error::BlockTooBig
88            | Error::HeaderChecksumError
89            | Error::ContentChecksumError
90            | Error::BlockChecksumError
91            | Error::ContentLengthError { .. } => io::Error::new(io::ErrorKind::InvalidData, e),
92        }
93    }
94}
95
96impl From<io::Error> for Error {
97    fn from(e: io::Error) -> Self {
98        match e.get_ref().map(|e| e.downcast_ref::<Error>()) {
99            Some(_) => *e.into_inner().unwrap().downcast::<Error>().unwrap(),
100            None => Error::IoError(e),
101        }
102    }
103}
104
105impl fmt::Display for Error {
106    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
107        write!(f, "{self:?}")
108    }
109}
110
111impl std::error::Error for Error {}