blob: 91d5cf6f925a7ce402199ae6c6cf7bed4daddaac [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
//! Compression codec support for HFile blocks.
use crate::hfile::error::{HFileError, Result};
use flate2::read::GzDecoder;
use std::io::Read;
/// Compression codec IDs used in HFile.
/// These IDs are stored in the HFile trailer and must not change.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CompressionCodec {
/// LZO compression (ID: 0)
Lzo = 0,
/// GZIP compression (ID: 1)
Gzip = 1,
/// No compression (ID: 2)
#[default]
None = 2,
/// Snappy compression (ID: 3)
Snappy = 3,
/// LZ4 compression (ID: 4)
Lz4 = 4,
/// BZIP2 compression (ID: 5)
Bzip2 = 5,
/// ZSTD compression (ID: 6)
Zstd = 6,
}
impl CompressionCodec {
/// Decode compression codec from ID stored in HFile.
pub fn from_id(id: u32) -> Result<Self> {
match id {
0 => Ok(CompressionCodec::Lzo),
1 => Ok(CompressionCodec::Gzip),
2 => Ok(CompressionCodec::None),
3 => Ok(CompressionCodec::Snappy),
4 => Ok(CompressionCodec::Lz4),
5 => Ok(CompressionCodec::Bzip2),
6 => Ok(CompressionCodec::Zstd),
_ => Err(HFileError::UnsupportedCompression(id)),
}
}
/// Decompress data using this codec.
///
/// # Arguments
/// * `compressed_data` - The compressed data bytes
/// * `uncompressed_size` - Expected size of uncompressed data
///
/// # Returns
/// Decompressed data as a byte vector
pub fn decompress(&self, compressed_data: &[u8], uncompressed_size: usize) -> Result<Vec<u8>> {
match self {
CompressionCodec::None => Ok(compressed_data.to_vec()),
CompressionCodec::Gzip => {
let mut decoder = GzDecoder::new(compressed_data);
let mut decompressed = Vec::with_capacity(uncompressed_size);
decoder.read_to_end(&mut decompressed).map_err(|e| {
HFileError::DecompressionError(format!("GZIP decompression failed: {}", e))
})?;
Ok(decompressed)
}
CompressionCodec::Lzo => Err(HFileError::DecompressionError(
"LZO compression not yet supported".to_string(),
)),
CompressionCodec::Snappy => Err(HFileError::DecompressionError(
"Snappy compression not yet supported".to_string(),
)),
CompressionCodec::Lz4 => Err(HFileError::DecompressionError(
"LZ4 compression not yet supported".to_string(),
)),
CompressionCodec::Bzip2 => Err(HFileError::DecompressionError(
"BZIP2 compression not yet supported".to_string(),
)),
CompressionCodec::Zstd => Err(HFileError::DecompressionError(
"ZSTD compression not yet supported".to_string(),
)),
}
}
}