Skip to main content

exarch_core/formats/
compression.rs

1//! Compression codec support for archive formats.
2//!
3//! This module provides unified handling of compression codecs used with
4//! TAR archives. The same compression codecs can be used for both reading
5//! (decompression) and writing (compression).
6//!
7//! # Supported Codecs
8//!
9//! - **Gzip** (.tar.gz, .tgz): Fast compression with good compatibility
10//! - **Bzip2** (.tar.bz2, .tbz2): Better compression ratio, slower
11//! - **Xz** (.tar.xz, .txz): Best compression ratio, slowest
12//! - **Zstd** (.tar.zst, .tzst): Modern codec with good speed/ratio balance
13
14/// Compression codec for archive files.
15///
16/// Represents the compression algorithm used for compressed archives.
17/// Each codec has different trade-offs between compression ratio,
18/// speed, and compatibility.
19///
20/// # Performance Characteristics
21///
22/// | Codec | Compression | Decompression | Ratio | Compatibility |
23/// |-------|-------------|---------------|-------|---------------|
24/// | Gzip  | Fast        | Fast          | Good  | Excellent     |
25/// | Bzip2 | Slow        | Medium        | Better| Good          |
26/// | Xz    | Very Slow   | Medium        | Best  | Good          |
27/// | Zstd  | Fast        | Very Fast     | Good  | Modern        |
28///
29/// # Examples
30///
31/// ```
32/// use exarch_core::formats::compression::CompressionCodec;
33///
34/// // Choose codec based on requirements
35/// let fast_codec = CompressionCodec::Gzip; // Fast compression
36/// let best_codec = CompressionCodec::Xz; // Best compression ratio
37/// let modern_codec = CompressionCodec::Zstd; // Modern balanced approach
38/// ```
39///
40/// `#[non_exhaustive]` so support for a new compression codec is not a
41/// breaking change for downstream matches.
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43#[non_exhaustive]
44pub enum CompressionCodec {
45    /// Gzip compression (deflate algorithm).
46    ///
47    /// Fast compression and decompression with widespread support.
48    /// Good default choice for most use cases.
49    Gzip,
50
51    /// Bzip2 compression (Burrows-Wheeler algorithm).
52    ///
53    /// Better compression ratio than gzip but slower.
54    /// Good for archives that will be distributed.
55    Bzip2,
56
57    /// Xz compression (LZMA2 algorithm).
58    ///
59    /// Best compression ratio but slowest.
60    /// Good for long-term storage or bandwidth-constrained transfers.
61    Xz,
62
63    /// Zstd compression (Zstandard algorithm).
64    ///
65    /// Modern codec with excellent speed and good compression ratio.
66    /// Good for archives that need fast decompression.
67    Zstd,
68}
69
70impl CompressionCodec {
71    /// Returns the typical file extension for this codec when used with TAR.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use exarch_core::formats::compression::CompressionCodec;
77    ///
78    /// assert_eq!(CompressionCodec::Gzip.extension(), "tar.gz");
79    /// assert_eq!(CompressionCodec::Bzip2.extension(), "tar.bz2");
80    /// assert_eq!(CompressionCodec::Xz.extension(), "tar.xz");
81    /// assert_eq!(CompressionCodec::Zstd.extension(), "tar.zst");
82    /// ```
83    #[must_use]
84    pub const fn extension(self) -> &'static str {
85        match self {
86            Self::Gzip => "tar.gz",
87            Self::Bzip2 => "tar.bz2",
88            Self::Xz => "tar.xz",
89            Self::Zstd => "tar.zst",
90        }
91    }
92
93    /// Returns a human-readable name for this codec.
94    ///
95    /// # Examples
96    ///
97    /// ```
98    /// use exarch_core::formats::compression::CompressionCodec;
99    ///
100    /// assert_eq!(CompressionCodec::Gzip.name(), "gzip");
101    /// assert_eq!(CompressionCodec::Bzip2.name(), "bzip2");
102    /// ```
103    #[must_use]
104    pub const fn name(self) -> &'static str {
105        match self {
106            Self::Gzip => "gzip",
107            Self::Bzip2 => "bzip2",
108            Self::Xz => "xz",
109            Self::Zstd => "zstd",
110        }
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117
118    #[test]
119    fn test_codec_extension() {
120        assert_eq!(CompressionCodec::Gzip.extension(), "tar.gz");
121        assert_eq!(CompressionCodec::Bzip2.extension(), "tar.bz2");
122        assert_eq!(CompressionCodec::Xz.extension(), "tar.xz");
123        assert_eq!(CompressionCodec::Zstd.extension(), "tar.zst");
124    }
125
126    #[test]
127    fn test_codec_name() {
128        assert_eq!(CompressionCodec::Gzip.name(), "gzip");
129        assert_eq!(CompressionCodec::Bzip2.name(), "bzip2");
130        assert_eq!(CompressionCodec::Xz.name(), "xz");
131        assert_eq!(CompressionCodec::Zstd.name(), "zstd");
132    }
133
134    #[test]
135    fn test_codec_equality() {
136        assert_eq!(CompressionCodec::Gzip, CompressionCodec::Gzip);
137        assert_ne!(CompressionCodec::Gzip, CompressionCodec::Bzip2);
138    }
139
140    #[test]
141    fn test_codec_hash() {
142        use std::collections::HashSet;
143
144        let mut set = HashSet::new();
145        set.insert(CompressionCodec::Gzip);
146        set.insert(CompressionCodec::Bzip2);
147        set.insert(CompressionCodec::Gzip); // Duplicate
148
149        assert_eq!(set.len(), 2);
150        assert!(set.contains(&CompressionCodec::Gzip));
151        assert!(set.contains(&CompressionCodec::Bzip2));
152    }
153}