1use crate::format::compression::Compression;
4use core::fmt;
5use std::{fmt::Debug, io};
6
7#[allow(deprecated)]
8#[derive(Copy, Clone, PartialEq, Eq, Debug)]
16#[cfg_attr(feature = "_arbitrary", derive(arbitrary::Arbitrary))]
17#[non_exhaustive]
18pub enum CompressionMethod {
19 Stored,
21 #[cfg(feature = "_deflate-any")]
23 Deflated,
24 #[cfg(feature = "deflate64")]
27 Deflate64,
28 #[cfg(feature = "_bzip2_any")]
30 Bzip2,
31 #[cfg(feature = "aes-crypto")]
36 Aes,
37 #[cfg(feature = "zstd")]
39 Zstd,
40 #[cfg(feature = "lzma")]
42 Lzma,
43 #[cfg(feature = "legacy-zip")]
44 Shrink,
46 #[cfg(feature = "legacy-zip")]
47 Reduce(u8),
49 #[cfg(feature = "legacy-zip")]
50 Implode,
52 #[cfg(feature = "xz")]
54 Xz,
55 #[cfg(feature = "ppmd")]
57 Ppmd,
58 #[cfg_attr(
60 not(any(fuzzing, feature = "_arbitrary")),
61 deprecated(since = "0.5.7", note = "use the constants instead")
62 )]
63 Unsupported(u16),
64}
65#[allow(deprecated, missing_docs)]
66impl CompressionMethod {
68 pub const STORE: Self = CompressionMethod::Stored;
69 #[cfg(feature = "legacy-zip")]
70 pub const SHRINK: Self = CompressionMethod::Shrink;
71 #[cfg(not(feature = "legacy-zip"))]
72 pub const SHRINK: Self = CompressionMethod::Unsupported(1);
74 #[cfg(feature = "legacy-zip")]
75 pub const REDUCE_1: Self = CompressionMethod::Reduce(1);
77 #[cfg(not(feature = "legacy-zip"))]
78 pub const REDUCE_1: Self = CompressionMethod::Unsupported(2);
80 #[cfg(feature = "legacy-zip")]
81 pub const REDUCE_2: Self = CompressionMethod::Reduce(2);
83 #[cfg(not(feature = "legacy-zip"))]
84 pub const REDUCE_2: Self = CompressionMethod::Unsupported(3);
86 #[cfg(feature = "legacy-zip")]
87 pub const REDUCE_3: Self = CompressionMethod::Reduce(3);
89 #[cfg(not(feature = "legacy-zip"))]
90 pub const REDUCE_3: Self = CompressionMethod::Unsupported(4);
92 #[cfg(feature = "legacy-zip")]
93 pub const REDUCE_4: Self = CompressionMethod::Reduce(4);
95 #[cfg(not(feature = "legacy-zip"))]
96 pub const REDUCE_4: Self = CompressionMethod::Unsupported(5);
98 #[cfg(feature = "legacy-zip")]
99 pub const IMPLODE: Self = CompressionMethod::Implode;
101 #[cfg(not(feature = "legacy-zip"))]
102 pub const IMPLODE: Self = CompressionMethod::Unsupported(6);
104 #[cfg(feature = "_deflate-any")]
105 pub const DEFLATE: Self = CompressionMethod::Deflated;
106 #[cfg(not(feature = "_deflate-any"))]
107 pub const DEFLATE: Self = CompressionMethod::Unsupported(8);
108 #[cfg(feature = "deflate64")]
109 pub const DEFLATE64: Self = CompressionMethod::Deflate64;
110 #[cfg(not(feature = "deflate64"))]
111 pub const DEFLATE64: Self = CompressionMethod::Unsupported(9);
112 pub const PKWARE_IMPLODE: Self = CompressionMethod::Unsupported(10);
113 #[cfg(feature = "_bzip2_any")]
114 pub const BZIP2: Self = CompressionMethod::Bzip2;
115 #[cfg(not(feature = "_bzip2_any"))]
116 pub const BZIP2: Self = CompressionMethod::Unsupported(12);
117 #[cfg(not(feature = "lzma"))]
118 pub const LZMA: Self = CompressionMethod::Unsupported(14);
119 #[cfg(feature = "lzma")]
120 pub const LZMA: Self = CompressionMethod::Lzma;
121 pub const IBM_ZOS_CMPSC: Self = CompressionMethod::Unsupported(16);
122 pub const IBM_TERSE: Self = CompressionMethod::Unsupported(18);
123 pub const ZSTD_DEPRECATED: Self = CompressionMethod::Unsupported(20);
124 #[cfg(feature = "zstd")]
125 pub const ZSTD: Self = CompressionMethod::Zstd;
126 #[cfg(not(feature = "zstd"))]
127 pub const ZSTD: Self = CompressionMethod::Unsupported(93);
128 pub const MP3: Self = CompressionMethod::Unsupported(94);
129 #[cfg(feature = "xz")]
130 pub const XZ: Self = CompressionMethod::Xz;
131 #[cfg(not(feature = "xz"))]
132 pub const XZ: Self = CompressionMethod::Unsupported(95);
133 pub const JPEG: Self = CompressionMethod::Unsupported(96);
134 pub const WAVPACK: Self = CompressionMethod::Unsupported(97);
135 #[cfg(feature = "ppmd")]
136 pub const PPMD: Self = CompressionMethod::Ppmd;
137 #[cfg(not(feature = "ppmd"))]
138 pub const PPMD: Self = CompressionMethod::Unsupported(98);
139 #[cfg(feature = "aes-crypto")]
140 pub const AES: Self = CompressionMethod::Aes;
141
142 #[cfg(not(feature = "aes-crypto"))]
145 pub const AES: Self = CompressionMethod::Unsupported(99);
146
147 #[cfg(feature = "_deflate-any")]
148 pub const DEFAULT: Self = CompressionMethod::Deflated;
149
150 #[cfg(all(not(feature = "_deflate-any"), feature = "_bzip2_any"))]
151 pub const DEFAULT: Self = CompressionMethod::Bzip2;
152
153 #[cfg(all(not(feature = "_deflate-any"), not(feature = "_bzip2_any")))]
154 pub const DEFAULT: Self = CompressionMethod::Stored;
155}
156impl CompressionMethod {
157 #[must_use]
159 pub const fn name_from_u16(val: u16) -> &'static str {
160 match val {
161 0 => "Stored",
162 1 => "Shrink",
163 2 => "Reduce(1)",
164 3 => "Reduce(2)",
165 4 => "Reduce(3)",
166 5 => "Reduce(4)",
167 6 => "Implode",
168 8 => "Deflated",
169 9 => "Deflate64",
170 12 => "Bzip2",
171 14 => "Lzma",
172 95 => "Xz",
173 93 => "Zstd",
174 98 => "Ppmd",
175 99 => "Aes",
176 _ => "Unknown",
177 }
178 }
179
180 pub(crate) const fn parse_from_u16(val: u16) -> Self {
181 match val {
182 0 => CompressionMethod::Stored,
183 #[cfg(feature = "legacy-zip")]
184 1 => CompressionMethod::Shrink,
185 #[cfg(feature = "legacy-zip")]
186 2 => CompressionMethod::Reduce(1),
187 #[cfg(feature = "legacy-zip")]
188 3 => CompressionMethod::Reduce(2),
189 #[cfg(feature = "legacy-zip")]
190 4 => CompressionMethod::Reduce(3),
191 #[cfg(feature = "legacy-zip")]
192 5 => CompressionMethod::Reduce(4),
193 #[cfg(feature = "legacy-zip")]
194 6 => CompressionMethod::Implode,
195 #[cfg(feature = "_deflate-any")]
196 8 => CompressionMethod::Deflated,
197 #[cfg(feature = "deflate64")]
198 9 => CompressionMethod::Deflate64,
199 #[cfg(feature = "_bzip2_any")]
200 12 => CompressionMethod::Bzip2,
201 #[cfg(feature = "lzma")]
202 14 => CompressionMethod::Lzma,
203 #[cfg(feature = "xz")]
204 95 => CompressionMethod::Xz,
205 #[cfg(feature = "zstd")]
206 93 => CompressionMethod::Zstd,
207 #[cfg(feature = "ppmd")]
208 98 => CompressionMethod::Ppmd,
209 #[cfg(feature = "aes-crypto")]
210 99 => CompressionMethod::Aes,
211 #[allow(deprecated)]
212 v => CompressionMethod::Unsupported(v),
213 }
214 }
215
216 #[deprecated(
218 since = "0.5.7",
219 note = "use a constant to construct a compression method"
220 )]
221 #[must_use]
222 pub const fn from_u16(val: u16) -> CompressionMethod {
223 Self::parse_from_u16(val)
224 }
225
226 pub(crate) const fn serialize_to_u16(self) -> u16 {
227 match self {
228 CompressionMethod::Stored => 0,
229 #[cfg(feature = "legacy-zip")]
230 CompressionMethod::Shrink => 1,
231 #[cfg(feature = "legacy-zip")]
232 CompressionMethod::Reduce(n) => 1 + n as u16,
233 #[cfg(feature = "legacy-zip")]
234 CompressionMethod::Implode => 6,
235
236 #[cfg(feature = "_deflate-any")]
237 CompressionMethod::Deflated => 8,
238 #[cfg(feature = "deflate64")]
239 CompressionMethod::Deflate64 => 9,
240 #[cfg(feature = "_bzip2_any")]
241 CompressionMethod::Bzip2 => 12,
242 #[cfg(feature = "zstd")]
243 CompressionMethod::Zstd => 93,
244 #[cfg(feature = "lzma")]
245 CompressionMethod::Lzma => 14,
246 #[cfg(feature = "xz")]
247 CompressionMethod::Xz => 95,
248 #[cfg(feature = "ppmd")]
249 CompressionMethod::Ppmd => 98,
250 #[cfg(feature = "aes-crypto")]
253 CompressionMethod::Aes => 99,
254 #[allow(deprecated)]
255 CompressionMethod::Unsupported(v) => v,
256 }
257 }
258
259 #[deprecated(
261 since = "0.5.7",
262 note = "to match on other compression methods, use a constant"
263 )]
264 #[must_use]
265 pub const fn to_u16(self) -> u16 {
266 self.serialize_to_u16()
267 }
268
269 #[must_use]
271 pub const fn into_compression(self) -> Compression {
272 match self {
273 CompressionMethod::Stored => Compression::Stored,
274 #[cfg(feature = "legacy-zip")]
275 CompressionMethod::Shrink => Compression::Shrink,
276 #[cfg(feature = "legacy-zip")]
277 CompressionMethod::Reduce(n) => match n {
278 1 => Compression::ReduceFactor1,
279 2 => Compression::ReduceFactor2,
280 3 => Compression::ReduceFactor3,
281 4 => Compression::ReduceFactor4,
282 _ => Compression::Unknown(n as u16),
283 },
284 #[cfg(feature = "legacy-zip")]
285 CompressionMethod::Implode => Compression::Implode,
286 #[cfg(feature = "_deflate-any")]
287 CompressionMethod::Deflated => Compression::Deflated,
288 #[cfg(feature = "deflate64")]
289 CompressionMethod::Deflate64 => Compression::Deflate64,
290 #[cfg(feature = "_bzip2_any")]
291 CompressionMethod::Bzip2 => Compression::Bzip2,
292 #[cfg(feature = "zstd")]
293 CompressionMethod::Zstd => Compression::Zstd,
294 #[cfg(feature = "lzma")]
295 CompressionMethod::Lzma => Compression::Lzma,
296 #[cfg(feature = "xz")]
297 CompressionMethod::Xz => Compression::Xz,
298 #[cfg(feature = "ppmd")]
299 CompressionMethod::Ppmd => Compression::Ppmd,
300 #[cfg(feature = "aes-crypto")]
303 CompressionMethod::Aes => Compression::Aes,
304 #[allow(deprecated)]
305 CompressionMethod::Unsupported(v) => Compression::Unknown(v),
306 }
307 }
308}
309
310impl From<CompressionMethod> for Compression {
311 fn from(value: CompressionMethod) -> Self {
312 value.into_compression()
313 }
314}
315
316impl Default for CompressionMethod {
317 #[cfg(feature = "_deflate-any")]
318 fn default() -> Self {
319 CompressionMethod::Deflated
320 }
321
322 #[cfg(not(feature = "_deflate-any"))]
323 fn default() -> Self {
324 CompressionMethod::Stored
325 }
326}
327
328impl fmt::Display for CompressionMethod {
329 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
330 let method_u16 = self.serialize_to_u16();
332 let name = Self::name_from_u16(method_u16);
333 write!(f, "{name}")
334 }
335}
336
337pub const SUPPORTED_COMPRESSION_METHODS: &[CompressionMethod] = &[
339 CompressionMethod::Stored,
340 #[cfg(feature = "_deflate-any")]
341 CompressionMethod::Deflated,
342 #[cfg(feature = "deflate64")]
343 CompressionMethod::Deflate64,
344 #[cfg(feature = "_bzip2_any")]
345 CompressionMethod::Bzip2,
346 #[cfg(feature = "zstd")]
347 CompressionMethod::Zstd,
348 #[cfg(feature = "xz")]
349 CompressionMethod::Xz,
350 #[cfg(feature = "ppmd")]
351 CompressionMethod::Ppmd,
352];
353
354#[cfg(feature = "zstd")]
355pub(crate) enum Zstd<R: io::BufRead> {
356 FailedToInitialize,
357 Initialized(zstd::Decoder<'static, R>),
358 Uninitialized(R),
359}
360
361pub(crate) enum Decompressor<R: io::BufRead> {
362 Stored(R),
363 #[cfg(feature = "deflate-flate2")]
364 Deflated(flate2::bufread::DeflateDecoder<R>),
365 #[cfg(feature = "deflate64")]
366 Deflate64(deflate64::Deflate64Decoder<R>),
367 #[cfg(feature = "_bzip2_any")]
368 Bzip2(bzip2::bufread::BzDecoder<R>),
369 #[cfg(feature = "zstd")]
370 Zstd(Zstd<R>),
371 #[cfg(feature = "lzma")]
372 Lzma(Lzma<R>),
373 #[cfg(feature = "legacy-zip")]
374 Shrink(crate::legacy::shrink::ShrinkDecoder<R>),
375 #[cfg(feature = "legacy-zip")]
376 Reduce(crate::legacy::reduce::ReduceDecoder<R>),
377 #[cfg(feature = "legacy-zip")]
378 Implode(crate::legacy::implode::ImplodeDecoder<R>),
379 #[cfg(feature = "xz")]
380 Xz(Box<lzma_rust2::XzReader<R>>),
381 #[cfg(feature = "ppmd")]
382 Ppmd(Ppmd<R>),
383}
384
385impl<R: io::BufRead> Debug for Decompressor<R> {
386 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
387 match self {
388 Self::Stored(_) => write!(f, "StoredDecompressor"),
389 #[cfg(feature = "deflate-flate2")]
390 Self::Deflated(_) => write!(f, "DeflatedDecompressor"),
391 #[cfg(feature = "deflate64")]
392 Self::Deflate64(_) => write!(f, "Deflate64Decompressor"),
393 #[cfg(feature = "_bzip2_any")]
394 Self::Bzip2(_) => write!(f, "Bzip2Decompressor"),
395 #[cfg(feature = "zstd")]
396 Self::Zstd(_) => write!(f, "ZstdDecompressor"),
397 #[cfg(feature = "lzma")]
398 Self::Lzma(_) => write!(f, "LzmaDecompressor"),
399 #[cfg(feature = "legacy-zip")]
400 Self::Shrink(_) => write!(f, "ShrinkDecompressor"),
401 #[cfg(feature = "legacy-zip")]
402 Self::Reduce(_) => write!(f, "ReduceDecompressor"),
403 #[cfg(feature = "legacy-zip")]
404 Self::Implode(_) => write!(f, "ImplodeDecompressor"),
405 #[cfg(feature = "xz")]
406 Self::Xz(_) => write!(f, "XzDecompressor"),
407 #[cfg(feature = "ppmd")]
408 Self::Ppmd(_) => write!(f, "PpmdDecompressor"),
409 }
410 }
411}
412
413#[cfg(feature = "lzma")]
414pub(crate) enum Lzma<R: io::BufRead> {
415 Uninitialized {
416 reader: Option<R>,
417 uncompressed_size: u64,
418 },
419 Initialized(Box<lzma_rust2::LzmaReader<R>>),
420}
421
422#[cfg(feature = "ppmd")]
423pub(crate) enum Ppmd<R: io::BufRead> {
424 Uninitialized(Option<R>),
425 Initialized(Box<ppmd_rust::Ppmd8Decoder<R>>),
426}
427
428impl<R: io::BufRead> io::Read for Decompressor<R> {
429 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
430 if buf.is_empty() {
431 return Ok(0);
432 }
433 match self {
434 Decompressor::Stored(r) => r.read(buf),
435 #[cfg(feature = "deflate-flate2")]
436 Decompressor::Deflated(r) => r.read(buf),
437 #[cfg(feature = "deflate64")]
438 Decompressor::Deflate64(r) => r.read(buf),
439 #[cfg(feature = "_bzip2_any")]
440 Decompressor::Bzip2(r) => r.read(buf),
441 #[cfg(feature = "zstd")]
442 Decompressor::Zstd(r) => {
443 let mut decoder = match core::mem::replace(r, Zstd::FailedToInitialize) {
444 Zstd::Initialized(decoder) => decoder,
445 Zstd::Uninitialized(inner) => zstd::Decoder::with_buffer(inner)?,
446 Zstd::FailedToInitialize => {
447 return Err(io::Error::other("Failed to start Zstd decoder"));
448 }
449 };
450 let result = decoder.read(buf);
451 *r = Zstd::Initialized(decoder);
452 result
453 }
454 #[cfg(feature = "lzma")]
455 Decompressor::Lzma(r) => match r {
456 Lzma::Uninitialized {
457 reader,
458 uncompressed_size,
459 } => {
460 let mut reader = reader.take().ok_or_else(|| {
461 io::Error::other("Reader was not set while reading LZMA data")
462 })?;
463
464 let mut header = [0; 4];
466 reader.read_exact(&mut header)?;
467 let _version_information =
468 u16::from_le_bytes(header[0..2].try_into().map_err(|e| {
469 std::io::Error::other(format!("Cannot transform header to u16: {e}"))
470 })?);
471 let properties_size =
472 u16::from_le_bytes(header[2..4].try_into().map_err(|e| {
473 std::io::Error::other(format!("Cannot transform header to u16: {e}"))
474 })?);
475 if properties_size != 5 {
476 return Err(io::Error::new(
477 io::ErrorKind::InvalidInput,
478 format!("unexpected LZMA properties size of {properties_size}"),
479 ));
480 }
481
482 let mut props_data = [0; 5];
483 reader.read_exact(&mut props_data)?;
484 let props = props_data[0];
485 let dict_size =
486 u32::from_le_bytes(props_data[1..5].try_into().map_err(|e| {
487 std::io::Error::other(format!("Cannot transform header to u32: {e}"))
488 })?);
489
490 let mut decompressor = lzma_rust2::LzmaReader::new_with_props(
493 reader,
494 *uncompressed_size,
495 props,
496 dict_size,
497 None,
498 )?;
499
500 let read = decompressor.read(buf)?;
501
502 *r = Lzma::Initialized(Box::new(decompressor));
503
504 Ok(read)
505 }
506 Lzma::Initialized(decompressor) => decompressor.read(buf),
507 },
508 #[cfg(feature = "xz")]
509 Decompressor::Xz(r) => r.read(buf),
510 #[cfg(feature = "ppmd")]
511 Decompressor::Ppmd(r) => match r {
512 Ppmd::Uninitialized(reader) => {
513 let mut reader = reader.take().ok_or_else(|| {
514 io::Error::other("Reader was not set while reading PPMd data")
515 })?;
516
517 let mut buffer = [0; 2];
518 reader.read_exact(&mut buffer)?;
519 let parameters = u16::from_le_bytes(buffer);
520
521 let order = u32::from((parameters & 0x0F) + 1);
522 let memory_size = 1024 * 1024 * u32::from(((parameters >> 4) & 0xFF) + 1);
523 let restoration_method = (parameters >> 12) & 0x0F;
524
525 let mut decompressor = ppmd_rust::Ppmd8Decoder::new(
526 reader,
527 order,
528 memory_size,
529 restoration_method.into(),
530 )
531 .map_err(|error| match error {
532 ppmd_rust::Error::RangeDecoderInitialization => io::Error::new(
533 io::ErrorKind::InvalidData,
534 "PPMd range coder initialization failed",
535 ),
536 ppmd_rust::Error::InvalidParameter => {
537 io::Error::new(io::ErrorKind::InvalidInput, "Invalid PPMd parameter")
538 }
539 ppmd_rust::Error::IoError(io_error) => io_error,
540 ppmd_rust::Error::MemoryAllocation => {
541 io::Error::new(io::ErrorKind::OutOfMemory, "Memory allocation failed")
542 }
543 })?;
544
545 let read = decompressor.read(buf)?;
546
547 *r = Ppmd::Initialized(Box::new(decompressor));
548
549 Ok(read)
550 }
551 Ppmd::Initialized(decompressor) => decompressor.read(buf),
552 },
553 #[cfg(feature = "legacy-zip")]
554 Decompressor::Shrink(r) => r.read(buf),
555 #[cfg(feature = "legacy-zip")]
556 Decompressor::Reduce(r) => r.read(buf),
557 #[cfg(feature = "legacy-zip")]
558 Decompressor::Implode(r) => r.read(buf),
559 }
560 }
561}
562
563impl<R: io::BufRead> Decompressor<R> {
564 pub fn new(
565 reader: R,
566 compression_method: CompressionMethod,
567 #[cfg_attr(not(any(feature = "lzma", feature = "legacy-zip")), allow(unused))]
568 uncompressed_size: u64,
569 #[cfg_attr(not(feature = "legacy-zip"), allow(unused))] flags: u16,
570 ) -> crate::result::ZipResult<Self> {
571 Ok(match compression_method {
572 CompressionMethod::Stored => Decompressor::Stored(reader),
573 #[cfg(feature = "deflate-flate2")]
574 CompressionMethod::Deflated => {
575 Decompressor::Deflated(flate2::bufread::DeflateDecoder::new(reader))
576 }
577 #[cfg(feature = "deflate64")]
578 CompressionMethod::Deflate64 => {
579 Decompressor::Deflate64(deflate64::Deflate64Decoder::with_buffer(reader))
580 }
581 #[cfg(feature = "_bzip2_any")]
582 CompressionMethod::Bzip2 => Decompressor::Bzip2(bzip2::bufread::BzDecoder::new(reader)),
583 #[cfg(feature = "zstd")]
584 CompressionMethod::Zstd => Decompressor::Zstd(Zstd::Uninitialized(reader)),
585 #[cfg(feature = "lzma")]
586 CompressionMethod::Lzma => Decompressor::Lzma(Lzma::Uninitialized {
587 reader: Some(reader),
588 uncompressed_size,
589 }),
590 #[cfg(feature = "xz")]
591 CompressionMethod::Xz => {
592 Decompressor::Xz(Box::new(lzma_rust2::XzReader::new(reader, false)))
593 }
594 #[cfg(feature = "ppmd")]
595 CompressionMethod::Ppmd => Decompressor::Ppmd(Ppmd::Uninitialized(Some(reader))),
596 #[cfg(feature = "legacy-zip")]
597 CompressionMethod::Shrink => Decompressor::Shrink(
598 crate::legacy::shrink::ShrinkDecoder::new(reader, uncompressed_size),
599 ),
600 #[cfg(feature = "legacy-zip")]
601 CompressionMethod::Reduce(n) => Decompressor::Reduce(
602 crate::legacy::reduce::ReduceDecoder::new(reader, uncompressed_size, n),
603 ),
604 #[cfg(feature = "legacy-zip")]
605 CompressionMethod::Implode => Decompressor::Implode(
606 crate::legacy::implode::ImplodeDecoder::new(reader, uncompressed_size, flags),
607 ),
608 method => {
609 let method = method.serialize_to_u16();
610 return Err(crate::result::ZipError::CompressionMethodNotSupported(
611 method,
612 ));
613 }
614 })
615 }
616
617 #[allow(clippy::infallible_destructuring_match)]
619 pub fn into_inner(self) -> io::Result<R> {
620 let inner = match self {
621 Decompressor::Stored(r) => r,
622 #[cfg(feature = "deflate-flate2")]
623 Decompressor::Deflated(r) => r.into_inner(),
624 #[cfg(feature = "deflate64")]
625 Decompressor::Deflate64(r) => r.into_inner(),
626 #[cfg(feature = "_bzip2_any")]
627 Decompressor::Bzip2(r) => r.into_inner(),
628 #[cfg(feature = "zstd")]
629 Decompressor::Zstd(Zstd::Initialized(r)) => r.finish(),
630 #[cfg(feature = "zstd")]
631 Decompressor::Zstd(Zstd::Uninitialized(r)) => r,
632 #[cfg(feature = "zstd")]
633 Decompressor::Zstd(Zstd::FailedToInitialize) => {
634 return Err(io::Error::other("Failed to start Zstd decoder"));
635 }
636 #[cfg(feature = "lzma")]
637 Decompressor::Lzma(r) => match r {
638 Lzma::Uninitialized { mut reader, .. } => reader
639 .take()
640 .ok_or_else(|| io::Error::other("Reader was not set"))?,
641 Lzma::Initialized(decoder) => decoder.into_inner(),
642 },
643 #[cfg(feature = "legacy-zip")]
644 Decompressor::Shrink(r) => r.into_inner(),
645 #[cfg(feature = "legacy-zip")]
646 Decompressor::Reduce(r) => r.into_inner(),
647 #[cfg(feature = "legacy-zip")]
648 Decompressor::Implode(r) => r.into_inner(),
649 #[cfg(feature = "xz")]
650 Decompressor::Xz(r) => r.into_inner(),
651 #[cfg(feature = "ppmd")]
652 Decompressor::Ppmd(r) => match r {
653 Ppmd::Uninitialized(mut reader) => reader
654 .take()
655 .ok_or_else(|| io::Error::other("Reader was not set"))?,
656 Ppmd::Initialized(decoder) => decoder.into_inner(),
657 },
658 };
659 Ok(inner)
660 }
661}
662
663#[cfg(test)]
664mod tests {
665 use super::{CompressionMethod, SUPPORTED_COMPRESSION_METHODS};
666
667 #[test]
668 fn from_eq_to() {
669 for v in 0..(u32::from(u16::MAX) + 1) {
670 let from = CompressionMethod::parse_from_u16(v as u16);
671 let to = u32::from(from.serialize_to_u16());
672 assert_eq!(v, to);
673 }
674 }
675
676 #[test]
677 fn to_eq_from() {
678 fn check_match(method: CompressionMethod) {
679 let to = method.serialize_to_u16();
680 let from = CompressionMethod::parse_from_u16(to);
681 let back = from.serialize_to_u16();
682 assert_eq!(to, back);
683 }
684
685 for &method in SUPPORTED_COMPRESSION_METHODS {
686 check_match(method);
687 }
688 }
689
690 #[test]
691 fn to_display_fmt() {
692 fn check_match(method: CompressionMethod) {
693 let debug_str = format!("{method:?}");
694 let display_str = format!("{method}");
695 assert_eq!(debug_str, display_str);
696 }
697
698 for &method in SUPPORTED_COMPRESSION_METHODS {
699 check_match(method);
700 }
701 }
702
703 #[cfg(feature = "legacy-zip")]
704 #[test]
705 fn check_reduce() {
706 assert_eq!(CompressionMethod::Reduce(1), CompressionMethod::REDUCE_1);
707 assert_eq!(CompressionMethod::Reduce(1).serialize_to_u16(), 2);
708 assert_eq!(CompressionMethod::REDUCE_1.serialize_to_u16(), 2);
709 }
710}