diff options
Diffstat (limited to 'src/frame/mod.rs')
-rw-r--r-- | src/frame/mod.rs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/frame/mod.rs b/src/frame/mod.rs new file mode 100644 index 0000000..8acfad2 --- /dev/null +++ b/src/frame/mod.rs @@ -0,0 +1,111 @@ +//! LZ4 Frame Format +//! +//! As defined in <https://github.com/lz4/lz4/blob/dev/doc/lz4_Frame_format.md> +//! +//! # Example: compress data on `stdin` with frame format +//! This program reads data from `stdin`, compresses it and emits it to `stdout`. +//! This example can be found in `examples/compress.rs`: +//! ```no_run +//! use std::io; +//! let stdin = io::stdin(); +//! let stdout = io::stdout(); +//! let mut rdr = stdin.lock(); +//! // Wrap the stdout writer in a LZ4 Frame writer. +//! let mut wtr = lz4_flex::frame::FrameEncoder::new(stdout.lock()); +//! io::copy(&mut rdr, &mut wtr).expect("I/O operation failed"); +//! wtr.finish().unwrap(); +//! ``` +//! + +use std::{fmt, io}; + +#[cfg_attr(feature = "safe-encode", forbid(unsafe_code))] +pub(crate) mod compress; +#[cfg_attr(feature = "safe-decode", forbid(unsafe_code))] +pub(crate) mod decompress; +pub(crate) mod header; + +pub use compress::{AutoFinishEncoder, FrameEncoder}; +pub use decompress::FrameDecoder; +pub use header::{BlockMode, BlockSize, FrameInfo}; + +#[derive(Debug)] +#[non_exhaustive] +/// Errors that can occur when de/compressing lz4. +pub enum Error { + /// Compression error. + CompressionError(crate::block::CompressError), + /// Decompression error. + DecompressionError(crate::block::DecompressError), + /// An io::Error was encountered. + IoError(io::Error), + /// Unsupported block size. + UnsupportedBlocksize(u8), + /// Unsupported frame version. + UnsupportedVersion(u8), + /// Wrong magic number for the LZ4 frame format. + WrongMagicNumber, + /// Reserved bits set. + ReservedBitsSet, + /// Block header is malformed. + InvalidBlockInfo, + /// Read a block larger than specified in the Frame header. + BlockTooBig, + /// The Frame header checksum doesn't match. + HeaderChecksumError, + /// The block checksum doesn't match. + BlockChecksumError, + /// The content checksum doesn't match. + ContentChecksumError, + /// Read an skippable frame. + /// The caller may read the specified amount of bytes from the underlying io::Read. + SkippableFrame(u32), + /// External dictionaries are not supported. + DictionaryNotSupported, + /// Content length differs. + ContentLengthError { + /// Expected content length. + expected: u64, + /// Actual content lenght. + actual: u64, + }, +} + +impl From<Error> for io::Error { + fn from(e: Error) -> Self { + match e { + Error::IoError(e) => e, + Error::CompressionError(_) + | Error::DecompressionError(_) + | Error::SkippableFrame(_) + | Error::DictionaryNotSupported => io::Error::new(io::ErrorKind::Other, e), + Error::WrongMagicNumber + | Error::UnsupportedBlocksize(..) + | Error::UnsupportedVersion(..) + | Error::ReservedBitsSet + | Error::InvalidBlockInfo + | Error::BlockTooBig + | Error::HeaderChecksumError + | Error::ContentChecksumError + | Error::BlockChecksumError + | Error::ContentLengthError { .. } => io::Error::new(io::ErrorKind::InvalidData, e), + } + } +} + +impl From<io::Error> for Error { + fn from(e: io::Error) -> Self { + match e.get_ref().map(|e| e.downcast_ref::<Error>()) { + Some(_) => *e.into_inner().unwrap().downcast::<Error>().unwrap(), + None => Error::IoError(e), + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result { + write!(f, "{self:?}") + } +} + +impl std::error::Error for Error {} |