box_format/
compression.rs

1use std::fmt;
2use std::io::{Read, Result, Seek, Write};
3
4#[cfg(feature = "brotli")]
5use comde::brotli::{BrotliCompressor, BrotliDecompressor};
6#[cfg(feature = "deflate")]
7use comde::deflate::{DeflateCompressor, DeflateDecompressor};
8#[cfg(feature = "snappy")]
9use comde::snappy::{SnappyCompressor, SnappyDecompressor};
10#[cfg(feature = "xz")]
11use comde::xz::{XzCompressor, XzDecompressor};
12#[cfg(feature = "zstd")]
13use comde::zstd::{ZstdCompressor, ZstdDecompressor};
14use comde::{
15    stored::{StoredCompressor, StoredDecompressor},
16    ByteCount, Compressor, Decompress, Decompressor,
17};
18
19pub mod constants {
20    pub const COMPRESSION_STORED: u8 = 0x00;
21    pub const COMPRESSION_DEFLATE: u8 = 0x10;
22    pub const COMPRESSION_ZSTD: u8 = 0x20;
23    pub const COMPRESSION_XZ: u8 = 0x30;
24    pub const COMPRESSION_SNAPPY: u8 = 0x40;
25    pub const COMPRESSION_BROTLI: u8 = 0x50;
26}
27
28use self::constants::*;
29
30#[derive(Clone, Copy, Eq, PartialEq)]
31pub enum Compression {
32    Stored,
33    Deflate,
34    Zstd,
35    Xz,
36    Snappy,
37    Brotli,
38    Unknown(u8),
39}
40
41impl Default for Compression {
42    fn default() -> Self {
43        Self::Stored
44    }
45}
46
47impl Compression {
48    pub const fn available_variants() -> &'static [&'static str] {
49        &["stored", "brotli", "deflate", "snappy", "xz", "zstd"]
50    }
51}
52
53impl fmt::Display for Compression {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        use Compression::*;
56
57        let s = match self {
58            Stored => "stored",
59            Deflate => "DEFLATE",
60            Zstd => "Zstd",
61            Xz => "xz",
62            Snappy => "Snappy",
63            Brotli => "Brotli",
64            Unknown(id) => return write!(f, "?{:x}?", id),
65        };
66
67        write!(f, "{}", s)
68    }
69}
70
71impl fmt::Debug for Compression {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        fmt::Display::fmt(self, f)
74    }
75}
76
77impl Compression {
78    pub const fn id(self) -> u8 {
79        use Compression::*;
80
81        match self {
82            Stored => COMPRESSION_STORED,
83            Deflate => COMPRESSION_DEFLATE,
84            Zstd => COMPRESSION_ZSTD,
85            Xz => COMPRESSION_XZ,
86            Snappy => COMPRESSION_SNAPPY,
87            Brotli => COMPRESSION_BROTLI,
88            Unknown(id) => id,
89        }
90    }
91
92    pub fn compress<W: Write + Seek, R: Read>(
93        self,
94        mut writer: W,
95        reader: &mut R,
96    ) -> Result<ByteCount> {
97        use Compression::*;
98
99        match self {
100            Stored => StoredCompressor.compress(&mut writer, reader),
101            #[cfg(feature = "deflate")]
102            Deflate => DeflateCompressor.compress(&mut writer, reader),
103            #[cfg(feature = "zstd")]
104            Zstd => ZstdCompressor.compress(&mut writer, reader),
105            #[cfg(feature = "xz")]
106            Xz => XzCompressor.compress(&mut writer, reader),
107            #[cfg(feature = "snappy")]
108            Snappy => SnappyCompressor.compress(&mut writer, reader),
109            #[cfg(feature = "brotli")]
110            Brotli => BrotliCompressor.compress(&mut writer, reader),
111            Unknown(id) => Err(std::io::Error::new(
112                std::io::ErrorKind::InvalidInput,
113                format!("Cannot handle compression with id {}", id),
114            )),
115            #[allow(unreachable_patterns)]
116            missing => Err(std::io::Error::new(
117                std::io::ErrorKind::InvalidInput,
118                format!("Compiled without support for {:?}", missing),
119            )),
120        }
121    }
122
123    pub fn decompress<R: Read, V: Decompress>(self, reader: R) -> Result<V> {
124        use Compression::*;
125
126        match self {
127            Stored => StoredDecompressor.from_reader(reader),
128            #[cfg(feature = "deflate")]
129            Deflate => DeflateDecompressor.from_reader(reader),
130            #[cfg(feature = "zstd")]
131            Zstd => ZstdDecompressor.from_reader(reader),
132            #[cfg(feature = "xz")]
133            Xz => XzDecompressor.from_reader(reader),
134            #[cfg(feature = "snappy")]
135            Snappy => SnappyDecompressor.from_reader(reader),
136            #[cfg(feature = "brotli")]
137            Brotli => BrotliDecompressor.from_reader(reader),
138            Unknown(id) => Err(std::io::Error::new(
139                std::io::ErrorKind::InvalidInput,
140                format!("Cannot handle decompression with id {}", id),
141            )),
142            #[allow(unreachable_patterns)]
143            missing => Err(std::io::Error::new(
144                std::io::ErrorKind::InvalidInput,
145                format!("Compiled without support for {:?}", missing),
146            )),
147        }
148    }
149
150    pub fn decompress_write<R: Read, W: Write>(self, reader: R, writer: W) -> Result<()> {
151        use Compression::*;
152
153        match self {
154            Stored => StoredDecompressor.copy(reader, writer),
155            #[cfg(feature = "deflate")]
156            Deflate => DeflateDecompressor.copy(reader, writer),
157            #[cfg(feature = "zstd")]
158            Zstd => ZstdDecompressor.copy(reader, writer),
159            #[cfg(feature = "xz")]
160            Xz => XzDecompressor.copy(reader, writer),
161            #[cfg(feature = "snappy")]
162            Snappy => SnappyDecompressor.copy(reader, writer),
163            #[cfg(feature = "brotli")]
164            Brotli => BrotliDecompressor.copy(reader, writer),
165            Unknown(id) => Err(std::io::Error::new(
166                std::io::ErrorKind::InvalidInput,
167                format!("Cannot handle decompression with id {}", id),
168            )),
169            #[allow(unreachable_patterns)]
170            missing => Err(std::io::Error::new(
171                std::io::ErrorKind::InvalidInput,
172                format!("Compiled without support for {:?}", missing),
173            )),
174        }?;
175
176        Ok(())
177    }
178}