use crate::format::compression::Compression;
use crate::result::ZipError;
use core::fmt;
use core::fmt::Debug;
use core::fmt::Formatter;
use core::mem::replace;
use core::panic::RefUnwindSafe;
use std::io;
use std::io::{BufRead, Read};
use std::panic::UnwindSafe;
#[allow(deprecated)]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "_arbitrary", derive(arbitrary::Arbitrary))]
#[non_exhaustive]
pub enum CompressionMethod {
Stored,
#[cfg(feature = "_deflate-any")]
Deflated,
#[cfg(feature = "deflate64")]
Deflate64,
#[cfg(feature = "_bzip2_any")]
Bzip2,
#[cfg(feature = "aes-crypto")]
Aes,
#[cfg(feature = "zstd")]
Zstd,
#[cfg(feature = "lzma")]
Lzma,
#[cfg(feature = "legacy-zip")]
Shrink,
#[cfg(feature = "legacy-zip")]
Reduce(u8),
#[cfg(feature = "legacy-zip")]
Implode,
#[cfg(feature = "xz")]
Xz,
#[cfg(feature = "ppmd")]
Ppmd,
#[cfg_attr(
not(any(fuzzing, feature = "_arbitrary")),
deprecated(since = "0.5.7", note = "use the constants instead")
)]
Unsupported(u16),
}
#[allow(deprecated, missing_docs)]
impl CompressionMethod {
pub const STORE: Self = CompressionMethod::Stored;
#[cfg(feature = "legacy-zip")]
pub const SHRINK: Self = CompressionMethod::Shrink;
#[cfg(not(feature = "legacy-zip"))]
pub const SHRINK: Self = CompressionMethod::Unsupported(1);
#[cfg(feature = "legacy-zip")]
pub const REDUCE_1: Self = CompressionMethod::Reduce(1);
#[cfg(not(feature = "legacy-zip"))]
pub const REDUCE_1: Self = CompressionMethod::Unsupported(2);
#[cfg(feature = "legacy-zip")]
pub const REDUCE_2: Self = CompressionMethod::Reduce(2);
#[cfg(not(feature = "legacy-zip"))]
pub const REDUCE_2: Self = CompressionMethod::Unsupported(3);
#[cfg(feature = "legacy-zip")]
pub const REDUCE_3: Self = CompressionMethod::Reduce(3);
#[cfg(not(feature = "legacy-zip"))]
pub const REDUCE_3: Self = CompressionMethod::Unsupported(4);
#[cfg(feature = "legacy-zip")]
pub const REDUCE_4: Self = CompressionMethod::Reduce(4);
#[cfg(not(feature = "legacy-zip"))]
pub const REDUCE_4: Self = CompressionMethod::Unsupported(5);
#[cfg(feature = "legacy-zip")]
pub const IMPLODE: Self = CompressionMethod::Implode;
#[cfg(not(feature = "legacy-zip"))]
pub const IMPLODE: Self = CompressionMethod::Unsupported(6);
#[cfg(feature = "_deflate-any")]
pub const DEFLATE: Self = CompressionMethod::Deflated;
#[cfg(not(feature = "_deflate-any"))]
pub const DEFLATE: Self = CompressionMethod::Unsupported(8);
#[cfg(feature = "deflate64")]
pub const DEFLATE64: Self = CompressionMethod::Deflate64;
#[cfg(not(feature = "deflate64"))]
pub const DEFLATE64: Self = CompressionMethod::Unsupported(9);
pub const PKWARE_IMPLODE: Self = CompressionMethod::Unsupported(10);
#[cfg(feature = "_bzip2_any")]
pub const BZIP2: Self = CompressionMethod::Bzip2;
#[cfg(not(feature = "_bzip2_any"))]
pub const BZIP2: Self = CompressionMethod::Unsupported(12);
#[cfg(not(feature = "lzma"))]
pub const LZMA: Self = CompressionMethod::Unsupported(14);
#[cfg(feature = "lzma")]
pub const LZMA: Self = CompressionMethod::Lzma;
pub const IBM_ZOS_CMPSC: Self = CompressionMethod::Unsupported(16);
pub const IBM_TERSE: Self = CompressionMethod::Unsupported(18);
pub const ZSTD_DEPRECATED: Self = CompressionMethod::Unsupported(20);
#[cfg(feature = "zstd")]
pub const ZSTD: Self = CompressionMethod::Zstd;
#[cfg(not(feature = "zstd"))]
pub const ZSTD: Self = CompressionMethod::Unsupported(93);
pub const MP3: Self = CompressionMethod::Unsupported(94);
#[cfg(feature = "xz")]
pub const XZ: Self = CompressionMethod::Xz;
#[cfg(not(feature = "xz"))]
pub const XZ: Self = CompressionMethod::Unsupported(95);
pub const JPEG: Self = CompressionMethod::Unsupported(96);
pub const WAVPACK: Self = CompressionMethod::Unsupported(97);
#[cfg(feature = "ppmd")]
pub const PPMD: Self = CompressionMethod::Ppmd;
#[cfg(not(feature = "ppmd"))]
pub const PPMD: Self = CompressionMethod::Unsupported(98);
#[cfg(feature = "aes-crypto")]
pub const AES: Self = CompressionMethod::Aes;
#[cfg(not(feature = "aes-crypto"))]
pub const AES: Self = CompressionMethod::Unsupported(99);
#[cfg(feature = "_deflate-any")]
pub const DEFAULT: Self = CompressionMethod::Deflated;
#[cfg(all(not(feature = "_deflate-any"), feature = "_bzip2_any"))]
pub const DEFAULT: Self = CompressionMethod::Bzip2;
#[cfg(all(not(feature = "_deflate-any"), not(feature = "_bzip2_any")))]
pub const DEFAULT: Self = CompressionMethod::Stored;
}
impl CompressionMethod {
#[must_use]
pub const fn name_from_u16(val: u16) -> &'static str {
match val {
0 => "Stored",
1 => "Shrink",
2 => "Reduce(1)",
3 => "Reduce(2)",
4 => "Reduce(3)",
5 => "Reduce(4)",
6 => "Implode",
8 => "Deflated",
9 => "Deflate64",
12 => "Bzip2",
14 => "Lzma",
95 => "Xz",
93 => "Zstd",
98 => "Ppmd",
99 => "Aes",
_ => "Unknown",
}
}
pub(crate) const fn parse_from_u16(val: u16) -> Self {
match val {
0 => CompressionMethod::Stored,
#[cfg(feature = "legacy-zip")]
1 => CompressionMethod::Shrink,
#[cfg(feature = "legacy-zip")]
2 => CompressionMethod::Reduce(1),
#[cfg(feature = "legacy-zip")]
3 => CompressionMethod::Reduce(2),
#[cfg(feature = "legacy-zip")]
4 => CompressionMethod::Reduce(3),
#[cfg(feature = "legacy-zip")]
5 => CompressionMethod::Reduce(4),
#[cfg(feature = "legacy-zip")]
6 => CompressionMethod::Implode,
#[cfg(feature = "_deflate-any")]
8 => CompressionMethod::Deflated,
#[cfg(feature = "deflate64")]
9 => CompressionMethod::Deflate64,
#[cfg(feature = "_bzip2_any")]
12 => CompressionMethod::Bzip2,
#[cfg(feature = "lzma")]
14 => CompressionMethod::Lzma,
#[cfg(feature = "xz")]
95 => CompressionMethod::Xz,
#[cfg(feature = "zstd")]
93 => CompressionMethod::Zstd,
#[cfg(feature = "ppmd")]
98 => CompressionMethod::Ppmd,
#[cfg(feature = "aes-crypto")]
99 => CompressionMethod::Aes,
#[allow(deprecated)]
v => CompressionMethod::Unsupported(v),
}
}
#[deprecated(
since = "0.5.7",
note = "use a constant to construct a compression method"
)]
#[must_use]
pub const fn from_u16(val: u16) -> CompressionMethod {
Self::parse_from_u16(val)
}
pub(crate) const fn serialize_to_u16(self) -> u16 {
match self {
CompressionMethod::Stored => 0,
#[cfg(feature = "legacy-zip")]
CompressionMethod::Shrink => 1,
#[cfg(feature = "legacy-zip")]
CompressionMethod::Reduce(n) => 1 + n as u16,
#[cfg(feature = "legacy-zip")]
CompressionMethod::Implode => 6,
#[cfg(feature = "_deflate-any")]
CompressionMethod::Deflated => 8,
#[cfg(feature = "deflate64")]
CompressionMethod::Deflate64 => 9,
#[cfg(feature = "_bzip2_any")]
CompressionMethod::Bzip2 => 12,
#[cfg(feature = "zstd")]
CompressionMethod::Zstd => 93,
#[cfg(feature = "lzma")]
CompressionMethod::Lzma => 14,
#[cfg(feature = "xz")]
CompressionMethod::Xz => 95,
#[cfg(feature = "ppmd")]
CompressionMethod::Ppmd => 98,
#[cfg(feature = "aes-crypto")]
CompressionMethod::Aes => 99,
#[allow(deprecated)]
CompressionMethod::Unsupported(v) => v,
}
}
#[deprecated(
since = "0.5.7",
note = "to match on other compression methods, use a constant"
)]
#[must_use]
pub const fn to_u16(self) -> u16 {
self.serialize_to_u16()
}
#[must_use]
pub const fn into_compression(self) -> Compression {
match self {
CompressionMethod::Stored => Compression::Stored,
#[cfg(feature = "legacy-zip")]
CompressionMethod::Shrink => Compression::Shrink,
#[cfg(feature = "legacy-zip")]
CompressionMethod::Reduce(n) => match n {
1 => Compression::ReduceFactor1,
2 => Compression::ReduceFactor2,
3 => Compression::ReduceFactor3,
4 => Compression::ReduceFactor4,
_ => Compression::Unknown(n as u16),
},
#[cfg(feature = "legacy-zip")]
CompressionMethod::Implode => Compression::Implode,
#[cfg(feature = "_deflate-any")]
CompressionMethod::Deflated => Compression::Deflated,
#[cfg(feature = "deflate64")]
CompressionMethod::Deflate64 => Compression::Deflate64,
#[cfg(feature = "_bzip2_any")]
CompressionMethod::Bzip2 => Compression::Bzip2,
#[cfg(feature = "zstd")]
CompressionMethod::Zstd => Compression::Zstd,
#[cfg(feature = "lzma")]
CompressionMethod::Lzma => Compression::Lzma,
#[cfg(feature = "xz")]
CompressionMethod::Xz => Compression::Xz,
#[cfg(feature = "ppmd")]
CompressionMethod::Ppmd => Compression::Ppmd,
#[cfg(feature = "aes-crypto")]
CompressionMethod::Aes => Compression::Aes,
#[allow(deprecated)]
CompressionMethod::Unsupported(v) => Compression::Unknown(v),
}
}
}
impl From<CompressionMethod> for Compression {
fn from(value: CompressionMethod) -> Self {
value.into_compression()
}
}
impl Default for CompressionMethod {
#[cfg(feature = "_deflate-any")]
fn default() -> Self {
CompressionMethod::Deflated
}
#[cfg(not(feature = "_deflate-any"))]
fn default() -> Self {
CompressionMethod::Stored
}
}
impl fmt::Display for CompressionMethod {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let method_u16 = self.serialize_to_u16();
let name = Self::name_from_u16(method_u16);
write!(f, "{name}")
}
}
pub const SUPPORTED_COMPRESSION_METHODS: &[CompressionMethod] = &[
CompressionMethod::Stored,
#[cfg(feature = "_deflate-any")]
CompressionMethod::Deflated,
#[cfg(feature = "deflate64")]
CompressionMethod::Deflate64,
#[cfg(feature = "_bzip2_any")]
CompressionMethod::Bzip2,
#[cfg(feature = "zstd")]
CompressionMethod::Zstd,
#[cfg(feature = "xz")]
CompressionMethod::Xz,
#[cfg(feature = "ppmd")]
CompressionMethod::Ppmd,
];
pub(crate) enum LazyDecompressor<R: BufRead> {
Uninitialized {
inner: R,
parameters: InstantiationParameters,
},
Initialized(Decompressor<R>),
Failed(Option<R>),
}
impl<R: BufRead> UnwindSafe for LazyDecompressor<R> {}
impl<R: BufRead> RefUnwindSafe for LazyDecompressor<R> {}
impl<R: BufRead> Debug for LazyDecompressor<R> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
LazyDecompressor::Uninitialized { parameters, .. } => {
f.write_fmt(format_args!("Uninitialized({parameters:?}"))
}
LazyDecompressor::Initialized(r) => f.write_fmt(format_args!("Initialized({r:?})")),
LazyDecompressor::Failed(None) => f.write_str("Failed (inner writer lost)"),
LazyDecompressor::Failed(Some(_)) => f.write_str("Failed (inner writer held)"),
}
}
}
#[derive(Default, Copy, Clone, Debug)]
pub(crate) struct InstantiationParameters {
pub(crate) compression_method: CompressionMethod,
#[cfg(any(feature = "lzma", feature = "legacy-zip"))]
pub(crate) uncompressed_size: u64,
#[cfg(feature = "legacy-zip")]
pub(crate) flags: u16,
}
fn instantiate<R: BufRead>(
#[cfg_attr(not(any(feature = "lzma", feature = "ppmd")), allow(unused_mut))] mut reader: R,
parameters: InstantiationParameters,
) -> Result<Decompressor<R>, (ZipError, Option<R>)> {
match parameters.compression_method {
CompressionMethod::Stored => Ok(Decompressor::Stored(reader)),
#[cfg(feature = "deflate-flate2")]
CompressionMethod::Deflated => Ok(Decompressor::Deflated(
flate2::bufread::DeflateDecoder::new(reader),
)),
#[cfg(feature = "deflate64")]
CompressionMethod::Deflate64 => Ok(Decompressor::Deflate64(
deflate64::Deflate64Decoder::with_buffer(reader),
)),
#[cfg(feature = "_bzip2_any")]
CompressionMethod::Bzip2 => Ok(Decompressor::Bzip2(bzip2::bufread::BzDecoder::new(reader))),
#[cfg(feature = "zstd")]
CompressionMethod::Zstd => {
let decoder = zstd::Decoder::try_with_buffer(reader)
.map_err(|(inner, e)| (ZipError::from(e), Some(inner)))?;
Ok(Decompressor::Zstd(decoder))
}
#[cfg(feature = "lzma")]
CompressionMethod::Lzma => {
fn check_properties_and_get_dict_size(
reader: &mut impl BufRead,
) -> crate::result::ZipResult<(u8, u32)> {
let mut header = [0; 4];
reader.read_exact(&mut header)?;
let version_bytes = header[0..2].try_into().map_err(|e| {
crate::result::invalid!("Cannot transform header to u16: {}", e)
})?;
let _version_information = u16::from_le_bytes(version_bytes);
let properties_size = u16::from_le_bytes(header[2..4].try_into().map_err(|e| {
crate::result::invalid!("Cannot transform header to u16: {}", e)
})?);
if properties_size != 5 {
return Err(crate::result::invalid!(
"unexpected LZMA properties size of {properties_size}"
));
}
let mut props_data = [0; 5];
reader.read_exact(&mut props_data)?;
let props = props_data[0];
let dict_size = u32::from_le_bytes(props_data[1..5].try_into().map_err(|e| {
crate::result::invalid!("Cannot transform header to u32: {}", e)
})?);
Ok((props, dict_size))
}
match check_properties_and_get_dict_size(&mut reader) {
Err(e) => Err((e, Some(reader))),
Ok((props, dict_size)) => Ok(Decompressor::Lzma(Box::new(
lzma_rust2::LzmaReader::new_with_props(
reader,
parameters.uncompressed_size,
props,
dict_size,
None,
)
.map_err(|e| (ZipError::from(e), None))?,
))),
}
}
#[cfg(feature = "xz")]
CompressionMethod::Xz => Ok(Decompressor::Xz(Box::new(lzma_rust2::XzReader::new(
reader, false,
)))),
#[cfg(feature = "ppmd")]
CompressionMethod::Ppmd => {
use crate::result::{ZipError, invalid};
fn parameters_from_headers(
reader: &mut impl BufRead,
) -> crate::result::ZipResult<(u32, u32, u16)> {
let mut buffer = [0; 2];
reader.read_exact(&mut buffer)?;
let parameters = u16::from_le_bytes(buffer);
let order = u32::from((parameters & 0x0F) + 1);
let memory_size = 1024 * 1024 * u32::from(((parameters >> 4) & 0xFF) + 1);
let restoration_method = (parameters >> 12) & 0x0F;
Ok((order, memory_size, restoration_method))
}
match parameters_from_headers(&mut reader) {
Ok((order, memory_size, restoration_method)) => Ok(Decompressor::Ppmd(Box::new(
ppmd_rust::Ppmd8Decoder::new(
reader,
order,
memory_size,
restoration_method.into(),
)
.map_err(|error| {
(
match error {
ppmd_rust::Error::RangeDecoderInitialization => {
invalid!("PPMd range coder initialization failed")
}
ppmd_rust::Error::InvalidParameter => {
invalid!("Invalid PPMd parameter")
}
ppmd_rust::Error::IoError(io_error) => ZipError::Io(io_error),
ppmd_rust::Error::MemoryAllocation => ZipError::Io(io::Error::new(
io::ErrorKind::OutOfMemory,
"Memory allocation failed",
)),
},
None,
)
})?,
))),
Err(e) => Err((e, Some(reader))),
}
}
#[cfg(feature = "legacy-zip")]
CompressionMethod::Shrink => Ok(Decompressor::Shrink(
crate::legacy::shrink::ShrinkDecoder::new(reader, parameters.uncompressed_size),
)),
#[cfg(feature = "legacy-zip")]
CompressionMethod::Reduce(n) => Ok(Decompressor::Reduce(
crate::legacy::reduce::ReduceDecoder::new(reader, parameters.uncompressed_size, n),
)),
#[cfg(feature = "legacy-zip")]
CompressionMethod::Implode => Ok(Decompressor::Implode(
crate::legacy::implode::ImplodeDecoder::new(
reader,
parameters.uncompressed_size,
parameters.flags,
),
)),
method => {
let method = method.serialize_to_u16();
Err((
ZipError::CompressionMethodNotSupported(method),
Some(reader),
))
}
}
}
impl<R: BufRead> Read for LazyDecompressor<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut decompressor = match replace(self, LazyDecompressor::Failed(None)) {
LazyDecompressor::Initialized(decompressor) => decompressor,
LazyDecompressor::Uninitialized { inner, parameters } => instantiate(inner, parameters)
.map_err(|(error, inner)| {
*self = LazyDecompressor::Failed(inner);
error
})?,
LazyDecompressor::Failed(inner) => {
*self = LazyDecompressor::Failed(inner);
return Err(io::Error::other(
"Decompressor previously failed to initialize or panicked while reading",
));
}
};
let result = decompressor.read(buf);
*self = LazyDecompressor::Initialized(decompressor);
result
}
}
pub(crate) enum Decompressor<R: BufRead> {
Stored(R),
#[cfg(feature = "deflate-flate2")]
Deflated(flate2::bufread::DeflateDecoder<R>),
#[cfg(feature = "deflate64")]
Deflate64(deflate64::Deflate64Decoder<R>),
#[cfg(feature = "_bzip2_any")]
Bzip2(bzip2::bufread::BzDecoder<R>),
#[cfg(feature = "zstd")]
Zstd(zstd::Decoder<'static, R>),
#[cfg(feature = "lzma")]
Lzma(Box<lzma_rust2::LzmaReader<R>>),
#[cfg(feature = "legacy-zip")]
Shrink(crate::legacy::shrink::ShrinkDecoder<R>),
#[cfg(feature = "legacy-zip")]
Reduce(crate::legacy::reduce::ReduceDecoder<R>),
#[cfg(feature = "legacy-zip")]
Implode(crate::legacy::implode::ImplodeDecoder<R>),
#[cfg(feature = "xz")]
Xz(Box<lzma_rust2::XzReader<R>>),
#[cfg(feature = "ppmd")]
Ppmd(Box<ppmd_rust::Ppmd8Decoder<R>>),
}
impl<R: BufRead> Debug for Decompressor<R> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Stored(_) => write!(f, "StoredDecompressor"),
#[cfg(feature = "deflate-flate2")]
Self::Deflated(_) => write!(f, "DeflatedDecompressor"),
#[cfg(feature = "deflate64")]
Self::Deflate64(_) => write!(f, "Deflate64Decompressor"),
#[cfg(feature = "_bzip2_any")]
Self::Bzip2(_) => write!(f, "Bzip2Decompressor"),
#[cfg(feature = "zstd")]
Self::Zstd(_) => write!(f, "ZstdDecompressor"),
#[cfg(feature = "lzma")]
Self::Lzma(_) => write!(f, "LzmaDecompressor"),
#[cfg(feature = "legacy-zip")]
Self::Shrink(_) => write!(f, "ShrinkDecompressor"),
#[cfg(feature = "legacy-zip")]
Self::Reduce(_) => write!(f, "ReduceDecompressor"),
#[cfg(feature = "legacy-zip")]
Self::Implode(_) => write!(f, "ImplodeDecompressor"),
#[cfg(feature = "xz")]
Self::Xz(_) => write!(f, "XzDecompressor"),
#[cfg(feature = "ppmd")]
Self::Ppmd(_) => write!(f, "PpmdDecompressor"),
}
}
}
impl<R: BufRead> Read for Decompressor<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if buf.is_empty() {
return Ok(0);
}
match self {
Decompressor::Stored(r) => r.read(buf),
#[cfg(feature = "deflate-flate2")]
Decompressor::Deflated(r) => r.read(buf),
#[cfg(feature = "deflate64")]
Decompressor::Deflate64(r) => r.read(buf),
#[cfg(feature = "_bzip2_any")]
Decompressor::Bzip2(r) => r.read(buf),
#[cfg(feature = "zstd")]
Decompressor::Zstd(r) => r.read(buf),
#[cfg(feature = "lzma")]
Decompressor::Lzma(r) => r.read(buf),
#[cfg(feature = "xz")]
Decompressor::Xz(r) => r.read(buf),
#[cfg(feature = "ppmd")]
Decompressor::Ppmd(r) => r.read(buf),
#[cfg(feature = "legacy-zip")]
Decompressor::Shrink(r) => r.read(buf),
#[cfg(feature = "legacy-zip")]
Decompressor::Reduce(r) => r.read(buf),
#[cfg(feature = "legacy-zip")]
Decompressor::Implode(r) => r.read(buf),
}
}
}
impl<R: BufRead> LazyDecompressor<R> {
pub fn new(reader: R, parameters: InstantiationParameters) -> Self {
LazyDecompressor::Uninitialized {
inner: reader,
parameters,
}
}
pub fn into_inner(self) -> io::Result<R> {
match self {
LazyDecompressor::Uninitialized { inner, .. } => Ok(inner),
LazyDecompressor::Failed(None) => Err(io::Error::other(
"Decompressor previously failed to initialize or panicked while reading",
)),
LazyDecompressor::Failed(Some(inner)) => Ok(inner),
LazyDecompressor::Initialized(d) => Ok(match d {
Decompressor::Stored(r) => r,
#[cfg(feature = "deflate-flate2")]
Decompressor::Deflated(r) => r.into_inner(),
#[cfg(feature = "deflate64")]
Decompressor::Deflate64(r) => r.into_inner(),
#[cfg(feature = "_bzip2_any")]
Decompressor::Bzip2(r) => r.into_inner(),
#[cfg(feature = "zstd")]
Decompressor::Zstd(r) => r.finish(),
#[cfg(feature = "lzma")]
Decompressor::Lzma(r) => r.into_inner(),
#[cfg(feature = "legacy-zip")]
Decompressor::Shrink(r) => r.into_inner(),
#[cfg(feature = "legacy-zip")]
Decompressor::Reduce(r) => r.into_inner(),
#[cfg(feature = "legacy-zip")]
Decompressor::Implode(r) => r.into_inner(),
#[cfg(feature = "xz")]
Decompressor::Xz(r) => r.into_inner(),
#[cfg(feature = "ppmd")]
Decompressor::Ppmd(r) => r.into_inner(),
}),
}
}
pub fn inner(&self) -> Option<&R> {
#[allow(clippy::infallible_destructuring_match)]
match self {
LazyDecompressor::Initialized(decompressor) => Some(match decompressor {
Decompressor::Stored(r) => r,
#[cfg(feature = "deflate-flate2")]
Decompressor::Deflated(r) => r.get_ref(),
#[cfg(feature = "deflate64")]
Decompressor::Deflate64(r) => r.get_ref(),
#[cfg(feature = "_bzip2_any")]
Decompressor::Bzip2(r) => r.get_ref(),
#[cfg(feature = "zstd")]
Decompressor::Zstd(r) => r.get_ref(),
#[cfg(feature = "lzma")]
Decompressor::Lzma(r) => r.inner(),
#[cfg(feature = "legacy-zip")]
Decompressor::Shrink(r) => r.inner(),
#[cfg(feature = "legacy-zip")]
Decompressor::Reduce(r) => r.inner(),
#[cfg(feature = "legacy-zip")]
Decompressor::Implode(r) => r.inner(),
#[cfg(feature = "xz")]
Decompressor::Xz(r) => r.inner(),
#[cfg(feature = "ppmd")]
Decompressor::Ppmd(r) => r.get_ref(),
}),
LazyDecompressor::Uninitialized { inner, .. } => Some(inner),
LazyDecompressor::Failed(maybe_inner) => maybe_inner.as_ref(),
}
}
}
#[cfg(test)]
mod tests {
use super::{CompressionMethod, SUPPORTED_COMPRESSION_METHODS};
#[test]
fn from_eq_to() {
for v in 0..(u32::from(u16::MAX) + 1) {
let from = CompressionMethod::parse_from_u16(v as u16);
let to = u32::from(from.serialize_to_u16());
assert_eq!(v, to);
}
}
#[test]
fn to_eq_from() {
fn check_match(method: CompressionMethod) {
let to = method.serialize_to_u16();
let from = CompressionMethod::parse_from_u16(to);
let back = from.serialize_to_u16();
assert_eq!(to, back);
}
for &method in SUPPORTED_COMPRESSION_METHODS {
check_match(method);
}
}
#[test]
fn to_display_fmt() {
fn check_match(method: CompressionMethod) {
let debug_str = format!("{method:?}");
let display_str = format!("{method}");
assert_eq!(debug_str, display_str);
}
for &method in SUPPORTED_COMPRESSION_METHODS {
check_match(method);
}
}
#[cfg(feature = "legacy-zip")]
#[test]
fn check_reduce() {
assert_eq!(CompressionMethod::Reduce(1), CompressionMethod::REDUCE_1);
assert_eq!(CompressionMethod::Reduce(1).serialize_to_u16(), 2);
assert_eq!(CompressionMethod::REDUCE_1.serialize_to_u16(), 2);
}
}