zip_merge/
compression.rs

1//! Possible ZIP compression methods.
2
3use cfg_if::cfg_if;
4use std::fmt;
5
6#[allow(deprecated)]
7/// Identifies the storage format used to compress a file within a ZIP archive.
8///
9/// Each file's compression method is stored alongside it, allowing the
10/// contents to be read without context.
11///
12/// When creating ZIP files, you may choose the method to use with
13/// [`crate::write::FileOptions::compression_method`]
14#[derive(Copy, Clone, PartialEq, Eq, Debug)]
15#[non_exhaustive]
16pub enum CompressionMethod {
17    /// Store the file as is
18    Stored,
19    /// Compress the file using Deflate
20    #[cfg(any(
21        feature = "deflate",
22        feature = "deflate-miniz",
23        feature = "deflate-zlib"
24    ))]
25    #[cfg_attr(
26        docsrs,
27        doc(cfg(any(
28            feature = "deflate",
29            feature = "deflate-miniz",
30            feature = "deflate-zlib"
31        )))
32    )]
33    Deflated,
34    /// Compress the file using BZIP2
35    #[cfg(feature = "bzip2")]
36    #[cfg_attr(docsrs, doc(cfg(feature = "bzip2")))]
37    Bzip2,
38    /// Encrypted using AES.
39    ///
40    /// The actual compression method has to be taken from the AES extra data field
41    /// or from `ZipFileData`.
42    #[cfg(feature = "aes-crypto")]
43    #[cfg_attr(docsrs, doc(cfg(feature = "aes-crypto")))]
44    Aes,
45    /// Compress the file using ZStandard
46    #[cfg(feature = "zstd")]
47    #[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
48    Zstd,
49    /// Unsupported compression method
50    #[deprecated(since = "0.5.7", note = "use the constants instead")]
51    Unsupported(u16),
52}
53#[allow(deprecated, missing_docs)]
54/// All compression methods defined for the ZIP format
55impl CompressionMethod {
56    pub const STORE: Self = CompressionMethod::Stored;
57    pub const SHRINK: Self = CompressionMethod::Unsupported(1);
58    pub const REDUCE_1: Self = CompressionMethod::Unsupported(2);
59    pub const REDUCE_2: Self = CompressionMethod::Unsupported(3);
60    pub const REDUCE_3: Self = CompressionMethod::Unsupported(4);
61    pub const REDUCE_4: Self = CompressionMethod::Unsupported(5);
62    pub const IMPLODE: Self = CompressionMethod::Unsupported(6);
63    cfg_if! {
64        if #[cfg(any(
65            feature = "deflate",
66            feature = "deflate-miniz",
67            feature = "deflate-zlib"
68        ))] {
69            #[cfg_attr(docsrs, doc(cfg(any(
70                feature = "deflate",
71                feature = "deflate-miniz",
72                feature = "deflate-zlib"
73            ))))]
74            pub const DEFLATE: Self = CompressionMethod::Deflated;
75        } else {
76            pub const DEFLATE: Self = CompressionMethod::Unsupported(8);
77        }
78    }
79    pub const DEFLATE64: Self = CompressionMethod::Unsupported(9);
80    pub const PKWARE_IMPLODE: Self = CompressionMethod::Unsupported(10);
81    cfg_if! {
82        if #[cfg(feature = "bzip2")] {
83            #[cfg_attr(docsrs, doc(cfg(feature = "bzip2")))]
84            pub const BZIP2: Self = CompressionMethod::Bzip2;
85        } else {
86            pub const BZIP2: Self = CompressionMethod::Unsupported(12);
87        }
88    }
89    pub const LZMA: Self = CompressionMethod::Unsupported(14);
90    pub const IBM_ZOS_CMPSC: Self = CompressionMethod::Unsupported(16);
91    pub const IBM_TERSE: Self = CompressionMethod::Unsupported(18);
92    pub const ZSTD_DEPRECATED: Self = CompressionMethod::Unsupported(20);
93    cfg_if! {
94        if #[cfg(feature = "zstd")] {
95            #[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
96            pub const ZSTD: Self = CompressionMethod::Zstd;
97        } else {
98            pub const ZSTD: Self = CompressionMethod::Unsupported(93);
99        }
100    }
101    pub const MP3: Self = CompressionMethod::Unsupported(94);
102    pub const XZ: Self = CompressionMethod::Unsupported(95);
103    pub const JPEG: Self = CompressionMethod::Unsupported(96);
104    pub const WAVPACK: Self = CompressionMethod::Unsupported(97);
105    pub const PPMD: Self = CompressionMethod::Unsupported(98);
106    cfg_if! {
107        if #[cfg(feature = "aes-crypto")] {
108            #[cfg_attr(docsrs, doc(cfg(feature = "aes-crypto")))]
109            pub const AES: Self = CompressionMethod::Aes;
110        } else {
111            pub const AES: Self = CompressionMethod::Unsupported(99);
112        }
113    }
114}
115impl CompressionMethod {
116    /// Converts an u16 to its corresponding CompressionMethod
117    #[deprecated(
118        since = "0.5.7",
119        note = "use a constant to construct a compression method"
120    )]
121    pub fn from_u16(val: u16) -> CompressionMethod {
122        #[allow(deprecated)]
123        match val {
124            0 => CompressionMethod::Stored,
125            #[cfg(any(
126                feature = "deflate",
127                feature = "deflate-miniz",
128                feature = "deflate-zlib"
129            ))]
130            8 => CompressionMethod::Deflated,
131            #[cfg(feature = "bzip2")]
132            12 => CompressionMethod::Bzip2,
133            #[cfg(feature = "zstd")]
134            93 => CompressionMethod::Zstd,
135            #[cfg(feature = "aes-crypto")]
136            99 => CompressionMethod::Aes,
137
138            v => CompressionMethod::Unsupported(v),
139        }
140    }
141
142    /// Converts a CompressionMethod to a u16
143    #[deprecated(
144        since = "0.5.7",
145        note = "to match on other compression methods, use a constant"
146    )]
147    pub fn to_u16(self) -> u16 {
148        #[allow(deprecated)]
149        match self {
150            CompressionMethod::Stored => 0,
151            #[cfg(any(
152                feature = "deflate",
153                feature = "deflate-miniz",
154                feature = "deflate-zlib"
155            ))]
156            CompressionMethod::Deflated => 8,
157            #[cfg(feature = "bzip2")]
158            CompressionMethod::Bzip2 => 12,
159            #[cfg(feature = "aes-crypto")]
160            CompressionMethod::Aes => 99,
161            #[cfg(feature = "zstd")]
162            CompressionMethod::Zstd => 93,
163
164            CompressionMethod::Unsupported(v) => v,
165        }
166    }
167}
168
169impl fmt::Display for CompressionMethod {
170    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171        // Just duplicate what the Debug format looks like, i.e, the enum key:
172        write!(f, "{self:?}")
173    }
174}
175
176/// The compression methods which have been implemented.
177pub const SUPPORTED_COMPRESSION_METHODS: &[CompressionMethod] = &[
178    CompressionMethod::Stored,
179    #[cfg(any(
180        feature = "deflate",
181        feature = "deflate-miniz",
182        feature = "deflate-zlib"
183    ))]
184    /* NB: these don't appear to show up in the docs. */
185    #[cfg_attr(docsrs, doc(cfg(any(
186        feature = "deflate",
187        feature = "deflate-miniz",
188        feature = "deflate-zlib"
189    ))))]
190    CompressionMethod::Deflated,
191    #[cfg(feature = "bzip2")]
192    #[cfg_attr(docsrs, doc(cfg(feature = "bzip2")))]
193    CompressionMethod::Bzip2,
194    #[cfg(feature = "zstd")]
195    #[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
196    CompressionMethod::Zstd,
197];
198
199#[cfg(test)]
200mod test {
201    use super::{CompressionMethod, SUPPORTED_COMPRESSION_METHODS};
202
203    #[test]
204    fn from_eq_to() {
205        for v in 0..(u16::MAX as u32 + 1) {
206            #[allow(deprecated)]
207            let from = CompressionMethod::from_u16(v as u16);
208            #[allow(deprecated)]
209            let to = from.to_u16() as u32;
210            assert_eq!(v, to);
211        }
212    }
213
214    #[test]
215    fn to_eq_from() {
216        fn check_match(method: CompressionMethod) {
217            #[allow(deprecated)]
218            let to = method.to_u16();
219            #[allow(deprecated)]
220            let from = CompressionMethod::from_u16(to);
221            #[allow(deprecated)]
222            let back = from.to_u16();
223            assert_eq!(to, back);
224        }
225
226        for &method in SUPPORTED_COMPRESSION_METHODS {
227            check_match(method);
228        }
229    }
230
231    #[test]
232    fn to_display_fmt() {
233        fn check_match(method: CompressionMethod) {
234            let debug_str = format!("{method:?}");
235            let display_str = format!("{method}");
236            assert_eq!(debug_str, display_str);
237        }
238
239        for &method in SUPPORTED_COMPRESSION_METHODS {
240            check_match(method);
241        }
242    }
243}