wow_mpq/compression/
methods.rs

1//! Compression method definitions and flags
2
3/// Compression method flags
4pub mod flags {
5    /// Huffman encoding (WAVE files only)
6    pub const HUFFMAN: u8 = 0x01;
7    /// Deflate/zlib compression
8    pub const ZLIB: u8 = 0x02;
9    /// PKWare Implode compression (older format, appears in newer MPQ v4 archives)
10    pub const IMPLODE: u8 = 0x04;
11    /// PKWare DCL compression
12    pub const PKWARE: u8 = 0x08;
13    /// BZip2 compression
14    pub const BZIP2: u8 = 0x10;
15    /// Sparse/RLE compression
16    pub const SPARSE: u8 = 0x20;
17    /// IMA ADPCM mono
18    pub const ADPCM_MONO: u8 = 0x40;
19    /// IMA ADPCM stereo
20    pub const ADPCM_STEREO: u8 = 0x80;
21    /// LZMA compression (not a flag combination)
22    pub const LZMA: u8 = 0x12;
23}
24
25/// Compression methods enum
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum CompressionMethod {
28    /// No compression
29    None,
30    /// Huffman encoding (WAVE files only)
31    Huffman,
32    /// Deflate/zlib compression
33    Zlib,
34    /// PKWare Implode compression
35    Implode,
36    /// PKWare DCL compression
37    PKWare,
38    /// BZip2 compression
39    BZip2,
40    /// Sparse/RLE compression
41    Sparse,
42    /// IMA ADPCM mono
43    AdpcmMono,
44    /// IMA ADPCM stereo
45    AdpcmStereo,
46    /// LZMA compression
47    Lzma,
48    /// Multiple compression methods applied in sequence
49    Multiple(u8),
50}
51
52impl CompressionMethod {
53    /// Determine compression method(s) from flags
54    pub fn from_flags(flags: u8) -> Self {
55        // Check for LZMA first (special case, not a bit flag)
56        if flags == flags::LZMA {
57            return CompressionMethod::Lzma;
58        }
59
60        // Check for single compression methods
61        match flags {
62            0 => CompressionMethod::None,
63            flags::HUFFMAN => CompressionMethod::Huffman,
64            flags::ZLIB => CompressionMethod::Zlib,
65            flags::IMPLODE => CompressionMethod::Implode,
66            flags::PKWARE => CompressionMethod::PKWare,
67            flags::BZIP2 => CompressionMethod::BZip2,
68            flags::SPARSE => CompressionMethod::Sparse,
69            flags::ADPCM_MONO => CompressionMethod::AdpcmMono,
70            flags::ADPCM_STEREO => CompressionMethod::AdpcmStereo,
71            _ => CompressionMethod::Multiple(flags),
72        }
73    }
74
75    /// Check if this is a multi-compression method
76    pub fn is_multiple(&self) -> bool {
77        matches!(self, CompressionMethod::Multiple(_))
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn test_compression_method_from_flags() {
87        assert_eq!(CompressionMethod::from_flags(0), CompressionMethod::None);
88        assert_eq!(
89            CompressionMethod::from_flags(flags::ZLIB),
90            CompressionMethod::Zlib
91        );
92        assert_eq!(
93            CompressionMethod::from_flags(flags::BZIP2),
94            CompressionMethod::BZip2
95        );
96        assert_eq!(
97            CompressionMethod::from_flags(flags::LZMA),
98            CompressionMethod::Lzma
99        );
100
101        // Multiple compression
102        let multi = flags::ZLIB | flags::PKWARE;
103        assert!(CompressionMethod::from_flags(multi).is_multiple());
104    }
105}