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}