#[cfg(feature = "zstd")]
pub mod ipc;
use std::io;
use crate::error::IoError;
use crate::arrow::message::org::apache::arrow::flatbuf::CompressionType;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Compression {
#[cfg(feature = "snappy")]
Snappy,
#[cfg(feature = "zstd")]
Zstd,
}
impl Compression {
pub fn to_arrow_ipc_type(self) -> io::Result<CompressionType> {
match self {
#[cfg(feature = "zstd")]
Compression::Zstd => Ok(CompressionType::ZSTD),
#[cfg(feature = "snappy")]
Compression::Snappy => Err(io::Error::new(
io::ErrorKind::Unsupported,
"Snappy is not part of the Arrow IPC (Flatbuffers metadata) specification for BodyCompression",
)),
}
}
}
#[cfg_attr(
not(any(feature = "snappy", feature = "zstd")),
allow(unused_variables)
)]
pub fn compress(input: &[u8], codec: Compression) -> Result<Vec<u8>, IoError> {
match codec {
#[cfg(feature = "snappy")]
Compression::Snappy => snappy_compress(input),
#[cfg(feature = "zstd")]
Compression::Zstd => zstd_compress(input),
}
}
#[cfg(feature = "snappy")]
fn snappy_compress(input: &[u8]) -> Result<Vec<u8>, IoError> {
use snap::raw::{Encoder, max_compress_len};
let mut encoder = Encoder::new();
let max_len = max_compress_len(input.len());
let mut out = vec![0u8; max_len];
let compressed_len = encoder
.compress(input, &mut out)
.map_err(|e| IoError::Compression(format!("Snappy compression failed: {:?}", e)))?;
out.truncate(compressed_len);
Ok(out)
}
#[cfg(feature = "zstd")]
fn zstd_compress(input: &[u8]) -> Result<Vec<u8>, IoError> {
zstd::stream::encode_all(input, 1)
.map_err(|e| IoError::Compression(format!("Zstd compression failed: {e}")))
}
#[cfg_attr(
not(any(feature = "snappy", feature = "zstd")),
allow(unused_variables)
)]
pub fn decompress(input: &[u8], codec: Compression) -> Result<Vec<u8>, IoError> {
match codec {
#[cfg(feature = "snappy")]
Compression::Snappy => snappy_decompress(input),
#[cfg(feature = "zstd")]
Compression::Zstd => zstd_decompress(input),
}
}
#[cfg(feature = "snappy")]
fn snappy_decompress(input: &[u8]) -> Result<Vec<u8>, IoError> {
use snap::raw::Decoder;
let mut decoder = Decoder::new();
decoder
.decompress_vec(input)
.map_err(|e| IoError::Compression(format!("Snappy decompression failed: {:?}", e)))
}
#[cfg(feature = "zstd")]
fn zstd_decompress(input: &[u8]) -> Result<Vec<u8>, IoError> {
zstd::stream::decode_all(input)
.map_err(|e| IoError::Compression(format!("Zstd decompression failed: {e}")))
}
pub fn parquet_codec_name(codec: Option<Compression>) -> &'static str {
match codec {
None => "UNCOMPRESSED",
#[cfg(feature = "snappy")]
Some(Compression::Snappy) => "SNAPPY",
#[cfg(feature = "zstd")]
Some(Compression::Zstd) => "ZSTD",
}
}