1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 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 {}