Add support for Gzip compression (includes .tar.gz)

This commit is contained in:
Vinícius Rodrigues Miguel 2021-03-24 17:03:49 -03:00
parent bdc16fdb17
commit 3fa939ac90
5 changed files with 103 additions and 58 deletions

View File

@ -1,4 +1,4 @@
use std::{fs, io::{self, Read, Write}, path::PathBuf};
use std::{fs, io::Write, path::PathBuf};
use colored::Colorize;
@ -9,38 +9,6 @@ use super::{Compressor, Entry};
pub struct BzipCompressor {}
struct CompressorToMemory {}
// impl CompressorToMemory {
// pub fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> OuchResult<Vec<u8>> {
// let mut buffer = vec![];
// if files.len() != 1 {
// eprintln!("{}: cannot compress multiple files directly to {:#?}.\n Try using an intermediate archival method such as Tar.\n Example: filename.tar{}", "error".red(), format, format);
// return Err(Error::InvalidInput);
// }
// let mut contents = Vec::new();
// let path = &files[0];
// ensure_exists(path)?;
// let bytes_read = {
// let bytes = fs::read(path)?;
// let mut encoder = get_encoder(&format, Box::new(&mut buffer));
// encoder.write_all(&*bytes)?;
// bytes.as_slice().read_to_end(&mut contents)?
// };
// println!("{}: compressed {:?} into memory ({} bytes)", "info".yellow(), &path, bytes_read);
// Ok(contents)
// }
// pub fn compress_bytes(file: File) {
// }
// }
impl BzipCompressor {
fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> OuchResult<Vec<u8>> {
if files.len() != 1 {
@ -82,13 +50,6 @@ impl BzipCompressor {
}
// TODO: customizable compression level
fn get_encoder<'a>(format: &CompressionFormat, buffer: Box<dyn io::Write + Send + 'a>) -> Box<dyn io::Write + Send + 'a> {
match format {
CompressionFormat::Bzip => Box::new(bzip2::write::BzEncoder::new(buffer, bzip2::Compression::new(4))),
_other => unreachable!()
}
}
impl Compressor for BzipCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
match from {

View File

@ -1,6 +1,7 @@
mod tar;
mod zip;
mod bzip;
mod tomemory;
mod compressor;
pub use compressor::Compressor;
@ -8,3 +9,4 @@ pub use self::compressor::Entry;
pub use self::tar::TarCompressor;
pub use self::zip::ZipCompressor;
pub use self::bzip::BzipCompressor;
pub use self::tomemory::GzipCompressor;

View File

@ -23,25 +23,8 @@ impl TarCompressor {
}
};
// let ok = EntryType::
println!("todo");
// let mut b = Builder::new(Vec::new());
// let mut header = Header::new_gnu();
// let name = b"././@LongLink";
// header.as_gnu_mut().unwrap().name[..name.len()].clone_from_slice(&name[..]);
// header.set_mode(0o644);
// header.set_uid(0);
// header.set_gid(0);
// header.set_mtime(0);
// // + 1 to be compliant with GNU tar
// header.set_size(size + 1);
// header.set_entry_type(EntryType::new(entry_type));
// header.set_cksum();
// Ok(b.into_inner()?)
Ok(vec![])
}

View File

@ -0,0 +1,97 @@
use std::{fs, io::{self, Read}, path::PathBuf};
use colored::Colorize;
use crate::{error::{Error, OuchResult}, extension::CompressionFormat, file::File};
use crate::utils::ensure_exists;
use super::{Compressor, Entry};
pub struct GzipCompressor {}
struct CompressorToMemory {}
impl CompressorToMemory {
pub fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> OuchResult<Vec<u8>> {
if files.len() != 1 {
eprintln!("{}: cannot compress multiple files directly to {:#?}.\n Try using an intermediate archival method such as Tar.\n Example: filename.tar{}", "error".red(), format, format);
return Err(Error::InvalidInput);
}
let mut contents = Vec::new();
let path = &files[0];
ensure_exists(path)?;
let bytes_written = {
let bytes = fs::read(path)?;
// let mut buffer = vec![];
// let mut encoder = get_encoder(&format, Box::new(&mut buffer));
// encoder.write_all(&*bytes)?;
// bytes.as_slice().read_to_end(&mut contents)?
Self::compress_bytes(&mut contents, bytes, format)?
};
println!(
"{}: compressed {:?} into memory ({} bytes)",
"info".yellow(),
&path,
bytes_written
);
Ok(contents)
}
pub fn compress_file_in_memory(file: File, format:CompressionFormat ) -> OuchResult<Vec<u8>> {
let mut compressed_contents = Vec::new();
let file_contents = match file.contents_in_memory {
Some(bytes) => bytes,
None => {
unreachable!();
}
};
let _bytes_written = Self::compress_bytes(&mut compressed_contents, file_contents, format);
Ok(compressed_contents)
}
pub fn compress_bytes(mut contents: &mut Vec<u8>, bytes_to_compress: Vec<u8>, format: CompressionFormat) -> OuchResult<usize> {
let mut buffer = vec![];
let mut encoder = get_encoder(&format, Box::new(&mut buffer));
encoder.write_all(&*bytes_to_compress)?;
Ok(bytes_to_compress.as_slice().read_to_end(&mut contents)?)
}
}
fn get_encoder<'a>(
format: &CompressionFormat,
buffer: Box<dyn io::Write + Send + 'a>,
) -> Box<dyn io::Write + Send + 'a> {
match format {
CompressionFormat::Gzip => Box::new(flate2::write::GzEncoder::new(
buffer,
flate2::Compression::default(),
)),
_other => unreachable!(),
}
}
impl Compressor for GzipCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
let format = CompressionFormat::Gzip;
match from {
Entry::Files(files) => Ok(
CompressorToMemory::compress_files(files, format)?
),
Entry::InMemory(file) => Ok(
CompressorToMemory::compress_file_in_memory(file, format)?
),
}
}
}

View File

@ -7,6 +7,7 @@ use crate::compressors::{
Compressor,
TarCompressor,
ZipCompressor,
GzipCompressor,
BzipCompressor,
};
@ -71,6 +72,7 @@ impl Evaluator {
CompressionFormat::Tar => Box::new(TarCompressor {}),
CompressionFormat::Zip => Box::new(ZipCompressor {}),
CompressionFormat::Bzip => Box::new(BzipCompressor {}),
CompressionFormat::Gzip => Box::new(GzipCompressor {}),
_other => todo!()
};