#[cfg(feature = "gzip")] use anyhow::Result; #[cfg(feature = "gzip")] use log::*; #[cfg(feature = "gzip")] use std::fs::File; #[cfg(feature = "gzip")] use std::io; #[cfg(feature = "gzip")] use std::io::{Read, Write}; #[cfg(feature = "gzip")] use std::path::PathBuf; #[cfg(feature = "gzip")] use flate2::Compression; #[cfg(feature = "gzip")] use flate2::read::GzDecoder; #[cfg(feature = "gzip")] use flate2::write::GzEncoder; #[cfg(feature = "gzip")] use crate::compression_engine::CompressionEngine; #[cfg(feature = "gzip")] #[derive(Debug, Eq, PartialEq, Clone, Default)] pub struct CompressionEngineGZip {} #[cfg(feature = "gzip")] impl CompressionEngineGZip { pub fn new() -> CompressionEngineGZip { CompressionEngineGZip {} } } #[cfg(feature = "gzip")] impl CompressionEngine for CompressionEngineGZip { fn is_supported(&self) -> bool { true } fn get_status_info(&self) -> (String, String, String) { ("".to_string(), "".to_string(), "".to_string()) } fn open(&self, file_path: PathBuf) -> Result> { debug!("COMPRESSION: Opening {:?} using {:?}", file_path, *self); let file = File::open(file_path)?; Ok(Box::new(GzDecoder::new(file))) } fn create(&self, file_path: PathBuf) -> Result> { debug!("COMPRESSION: Writing 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))) } fn clone_box(&self) -> Box { Box::new(self.clone()) } } #[cfg(feature = "gzip")] #[derive(Debug)] pub struct AutoFinishGzEncoder { encoder: Option>, } #[cfg(feature = "gzip")] impl AutoFinishGzEncoder { fn new(gz_encoder: GzEncoder) -> AutoFinishGzEncoder { AutoFinishGzEncoder { encoder: Some(gz_encoder), } } } #[cfg(feature = "gzip")] impl Drop for AutoFinishGzEncoder { fn drop(&mut self) { if let Some(encoder) = self.encoder.take() { debug!("COMPRESSION: Finishing"); if let Err(e) = encoder.finish() { warn!("Failed to finish GZip encoder: {}", e); } } } } #[cfg(feature = "gzip")] impl Write for AutoFinishGzEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.encoder.as_mut().unwrap().write(buf) } fn flush(&mut self) -> io::Result<()> { self.encoder.as_mut().unwrap().flush() } }