summavy/store/
decompressors.rs

1use std::io;
2
3use serde::{Deserialize, Serialize};
4
5use super::Compressor;
6
7pub trait StoreCompressor {
8    fn compress(&self, uncompressed: &[u8], compressed: &mut Vec<u8>) -> io::Result<()>;
9    fn decompress(&self, compressed: &[u8], decompressed: &mut Vec<u8>) -> io::Result<()>;
10    fn get_compressor_id() -> u8;
11}
12
13/// Decompressor is deserialized from the doc store footer, when opening an index.
14#[derive(Clone, Debug, Copy, PartialEq, Eq, Serialize, Deserialize)]
15pub enum Decompressor {
16    /// No compression
17    None,
18    /// Use the lz4 decompressor (block format)
19    Lz4,
20    /// Use the brotli decompressor
21    Brotli,
22    /// Use the snap decompressor
23    Snappy,
24    /// Use the zstd decompressor
25    Zstd,
26}
27
28impl From<Compressor> for Decompressor {
29    fn from(compressor: Compressor) -> Self {
30        match compressor {
31            Compressor::None => Decompressor::None,
32            Compressor::Lz4 => Decompressor::Lz4,
33            Compressor::Brotli => Decompressor::Brotli,
34            Compressor::Snappy => Decompressor::Snappy,
35            Compressor::Zstd(_) => Decompressor::Zstd,
36        }
37    }
38}
39
40impl Decompressor {
41    pub(crate) fn from_id(id: u8) -> Decompressor {
42        match id {
43            0 => Decompressor::None,
44            1 => Decompressor::Lz4,
45            2 => Decompressor::Brotli,
46            3 => Decompressor::Snappy,
47            4 => Decompressor::Zstd,
48            _ => panic!("unknown compressor id {:?}", id),
49        }
50    }
51
52    pub(crate) fn get_id(&self) -> u8 {
53        match self {
54            Self::None => 0,
55            Self::Lz4 => 1,
56            Self::Brotli => 2,
57            Self::Snappy => 3,
58            Self::Zstd => 4,
59        }
60    }
61
62    pub(crate) fn decompress(&self, compressed_block: &[u8]) -> io::Result<Vec<u8>> {
63        let mut decompressed_block = vec![];
64        self.decompress_into(compressed_block, &mut decompressed_block)?;
65        Ok(decompressed_block)
66    }
67
68    #[inline]
69    pub(crate) fn decompress_into(
70        &self,
71        compressed: &[u8],
72        decompressed: &mut Vec<u8>,
73    ) -> io::Result<()> {
74        match self {
75            Self::None => {
76                decompressed.clear();
77                decompressed.extend_from_slice(compressed);
78                Ok(())
79            }
80            Self::Lz4 => {
81                #[cfg(feature = "lz4-compression")]
82                {
83                    super::compression_lz4_block::decompress(compressed, decompressed)
84                }
85                #[cfg(not(feature = "lz4-compression"))]
86                {
87                    panic!("lz4-compression feature flag not activated");
88                }
89            }
90            Self::Brotli => {
91                #[cfg(feature = "brotli-compression")]
92                {
93                    super::compression_brotli::decompress(compressed, decompressed)
94                }
95                #[cfg(not(feature = "brotli-compression"))]
96                {
97                    panic!("brotli-compression feature flag not activated");
98                }
99            }
100            Self::Snappy => {
101                #[cfg(feature = "snappy-compression")]
102                {
103                    super::compression_snap::decompress(compressed, decompressed)
104                }
105                #[cfg(not(feature = "snappy-compression"))]
106                {
107                    panic!("snappy-compression feature flag not activated");
108                }
109            }
110            Self::Zstd => {
111                #[cfg(feature = "zstd-compression")]
112                {
113                    super::compression_zstd_block::decompress(compressed, decompressed)
114                }
115                #[cfg(not(feature = "zstd-compression"))]
116                {
117                    panic!("zstd-compression feature flag not activated");
118                }
119            }
120        }
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127    use crate::store::Compressor;
128
129    #[test]
130    fn compressor_decompressor_id_test() {
131        assert_eq!(Decompressor::from(Compressor::None), Decompressor::None);
132        assert_eq!(Decompressor::from(Compressor::Lz4), Decompressor::Lz4);
133        assert_eq!(Decompressor::from(Compressor::Brotli), Decompressor::Brotli);
134        assert_eq!(Decompressor::from(Compressor::Snappy), Decompressor::Snappy);
135        assert_eq!(
136            Decompressor::from(Compressor::Zstd(Default::default())),
137            Decompressor::Zstd
138        );
139    }
140}