Add internal gzip compression
This commit is contained in:
@@ -10,11 +10,13 @@ use enum_map::{EnumMap,Enum};
|
|||||||
|
|
||||||
pub mod none;
|
pub mod none;
|
||||||
pub mod lz4;
|
pub mod lz4;
|
||||||
|
pub mod gzip;
|
||||||
pub mod program;
|
pub mod program;
|
||||||
|
|
||||||
use none::CompressionEngineNone;
|
use none::CompressionEngineNone;
|
||||||
use lz4::CompressionEngineLZ4;
|
use lz4::CompressionEngineLZ4;
|
||||||
use program::CompressionProgram;
|
use program::CompressionProgram;
|
||||||
|
use gzip::CompressionEngineGZip;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, strum::EnumIter, strum::Display, strum::EnumString, Enum)]
|
#[derive(Debug, Eq, PartialEq, Clone, strum::EnumIter, strum::Display, strum::EnumString, Enum)]
|
||||||
#[strum(ascii_case_insensitive)]
|
#[strum(ascii_case_insensitive)]
|
||||||
@@ -38,7 +40,7 @@ pub trait CompressionEngine {
|
|||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref COMPRESSION_PROGRAMS: EnumMap<CompressionType, Option<CompressionProgram>> = enum_map! {
|
pub static ref COMPRESSION_PROGRAMS: EnumMap<CompressionType, Option<CompressionProgram>> = enum_map! {
|
||||||
CompressionType::LZ4 => None,
|
CompressionType::LZ4 => None,
|
||||||
CompressionType::GZip => Some(CompressionProgram::new("gzip", vec!["-qcf"], vec!["-dcf"])),
|
CompressionType::GZip => None,
|
||||||
CompressionType::BZip2 => Some(CompressionProgram::new("bzip2", vec!["-qcf"], vec!["-dcf"])),
|
CompressionType::BZip2 => Some(CompressionProgram::new("bzip2", vec!["-qcf"], vec!["-dcf"])),
|
||||||
CompressionType::XZ => Some(CompressionProgram::new("xz", vec!["-qcf"], vec!["-dcf"])),
|
CompressionType::XZ => Some(CompressionProgram::new("xz", vec!["-qcf"], vec!["-dcf"])),
|
||||||
CompressionType::ZStd => Some(CompressionProgram::new("zstd", vec!["-qcf"], vec!["-dcf"])),
|
CompressionType::ZStd => Some(CompressionProgram::new("zstd", vec!["-qcf"], vec!["-dcf"])),
|
||||||
@@ -49,8 +51,9 @@ lazy_static! {
|
|||||||
|
|
||||||
pub fn get_engine(compression_type: CompressionType) -> Result<Box<dyn CompressionEngine>> {
|
pub fn get_engine(compression_type: CompressionType) -> Result<Box<dyn CompressionEngine>> {
|
||||||
match compression_type {
|
match compression_type {
|
||||||
CompressionType::None => Ok(Box::new(CompressionEngineNone::new())),
|
|
||||||
CompressionType::LZ4 => Ok(Box::new(CompressionEngineLZ4::new())),
|
CompressionType::LZ4 => Ok(Box::new(CompressionEngineLZ4::new())),
|
||||||
|
CompressionType::GZip => Ok(Box::new(CompressionEngineGZip::new())),
|
||||||
|
CompressionType::None => Ok(Box::new(CompressionEngineNone::new())),
|
||||||
compression_type => Ok(Box::new(COMPRESSION_PROGRAMS[compression_type.clone()].clone().unwrap()))
|
compression_type => Ok(Box::new(COMPRESSION_PROGRAMS[compression_type.clone()].clone().unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
80
src/compression/gzip.rs
Normal file
80
src/compression/gzip.rs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use log::*;
|
||||||
|
|
||||||
|
use flate2::Compression;
|
||||||
|
use flate2::read::GzDecoder;
|
||||||
|
use flate2::write::GzEncoder;
|
||||||
|
|
||||||
|
use crate::compression::CompressionEngine;
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Clone, Default)]
|
||||||
|
pub struct CompressionEngineGZip {}
|
||||||
|
|
||||||
|
impl CompressionEngineGZip {
|
||||||
|
pub fn new() -> CompressionEngineGZip {
|
||||||
|
CompressionEngineGZip {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompressionEngine for CompressionEngineGZip {
|
||||||
|
fn is_supported(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cat(&self, file_path: PathBuf) -> Result<()> {
|
||||||
|
debug!("COMPRESSION: Outputting {:?} to STDOUT using {:?}", file_path, *self);
|
||||||
|
|
||||||
|
let mut stdout = io::stdout().lock();
|
||||||
|
let file = File::open(file_path)?;
|
||||||
|
let mut gzip_read = GzDecoder::new(file);
|
||||||
|
|
||||||
|
io::copy(&mut gzip_read, &mut stdout)?;
|
||||||
|
stdout.flush()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(&self, file_path: PathBuf) -> Result<Box<dyn Write>> {
|
||||||
|
debug!("COMPRESSION: Writting to {:?} using {:?}", file_path, *self);
|
||||||
|
|
||||||
|
let file = File::create(file_path)?;
|
||||||
|
let gzip_write = GzEncoder::new(file, Compression::default());
|
||||||
|
|
||||||
|
Ok(Box::new(AutoFinishGzEncoder::new(gzip_write)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AutoFinishGzEncoder<W: Write> {
|
||||||
|
encoder: Option<GzEncoder<W>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Write> AutoFinishGzEncoder<W> {
|
||||||
|
fn new(gz_encoder: GzEncoder<W>) -> AutoFinishGzEncoder<W> {
|
||||||
|
AutoFinishGzEncoder {
|
||||||
|
encoder: Some(gz_encoder),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Write> Drop for AutoFinishGzEncoder<W> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(encoder) = self.encoder.take() {
|
||||||
|
debug!("COMPRESSION: Finishing");
|
||||||
|
let _ = encoder.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Write> Write for AutoFinishGzEncoder<W> {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
self.encoder.as_mut().unwrap().write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
self.encoder.as_mut().unwrap().flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user