tibba_util/
compression.rs

1// Copyright 2025 Tree xie.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use super::Error;
16use lz4_flex::block::{compress_prepend_size, decompress_size_prepended};
17
18// Custom Result type using the crate's Error type
19type Result<T> = std::result::Result<T, Error>;
20
21/// An enum to represent supported compression algorithms and their parameters.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum Algorithm {
24    /// LZ4 algorithm.
25    Lz4,
26    /// Zstandard (zstd) algorithm, can specify compression level.
27    Zstd(i32),
28}
29
30/// Provide a default implementation for Algorithm, for easy use.
31impl Default for Algorithm {
32    fn default() -> Self {
33        // Default to using zstd's default compression level, as it usually has a good balance between compression ratio and speed.
34        Algorithm::Zstd(zstd::DEFAULT_COMPRESSION_LEVEL)
35    }
36}
37
38/// Compress data using the specified algorithm.
39///
40/// # Arguments
41/// * `data` - Original data bytes.
42/// * `algorithm` - The compression algorithm to use (`Algorithm::Lz4` or `Algorithm::Zstd(level)`).
43///
44/// # Returns
45/// * `Result<Vec<u8>>` - Compressed data or error.
46pub fn compress(data: &[u8], algorithm: Algorithm) -> Result<Vec<u8>> {
47    match algorithm {
48        Algorithm::Lz4 => {
49            // LZ4's compression function does not return an error, so we wrap it in Ok.
50            Ok(compress_prepend_size(data))
51        }
52        Algorithm::Zstd(level) => {
53            // Optimization: use zstd::encode_all, code is more concise.
54            zstd::encode_all(data, level).map_err(|e| Error::Zstd { source: e })
55        }
56    }
57}
58
59/// Decompress data using the specified algorithm.
60///
61/// # Arguments
62/// * `data` - Compressed data bytes.
63/// * `algorithm` - The compression algorithm used.
64///
65/// # Returns
66/// * `Result<Vec<u8>>` - Decompressed data or error.
67pub fn decompress(data: &[u8], algorithm: Algorithm) -> Result<Vec<u8>> {
68    match algorithm {
69        Algorithm::Lz4 => {
70            decompress_size_prepended(data).map_err(|e| Error::Lz4Decompress { source: e })
71        }
72        // Decompression does not require compression level, so ignore the level parameter of Zstd.
73        Algorithm::Zstd(_) => {
74            // Optimization: use zstd::decode_all, code is more concise.
75            zstd::decode_all(data).map_err(|e| Error::Zstd { source: e })
76        }
77    }
78}