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 
20 use std::{fmt, io};
21 
22 #[cfg_attr(feature = "safe-encode", forbid(unsafe_code))]
23 pub(crate) mod compress;
24 #[cfg_attr(feature = "safe-decode", forbid(unsafe_code))]
25 pub(crate) mod decompress;
26 pub(crate) mod header;
27 
28 pub use compress::{AutoFinishEncoder, FrameEncoder};
29 pub use decompress::FrameDecoder;
30 pub use header::{BlockMode, BlockSize, FrameInfo};
31 
32 #[derive(Debug)]
33 #[non_exhaustive]
34 /// Errors that can occur when de/compressing lz4.
35 pub 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 
74 impl From<Error> for io::Error {
from(e: Error) -> Self75     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 
96 impl From<io::Error> for Error {
from(e: io::Error) -> Self97     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 
105 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result106     fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
107         write!(f, "{self:?}")
108     }
109 }
110 
111 impl std::error::Error for Error {}
112