Fixes Gzip and Lzma compression

This commit is contained in:
Vinícius Rodrigues Miguel 2021-03-24 17:40:38 -03:00
parent f3dd4d9804
commit 0b346eee3d
5 changed files with 147 additions and 119 deletions

72
src/compressors/gzip.rs Normal file
View File

@ -0,0 +1,72 @@
use std::{fs, io::Write, 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 {}
impl GzipCompressor {
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 path = &files[0];
ensure_exists(path)?;
let bytes = {
let bytes = fs::read(path)?;
Self::compress_bytes(bytes)?
};
println!(
"{}: compressed {:?} into memory ({} bytes)",
"info".yellow(),
&path,
bytes.len()
);
Ok(bytes)
}
pub fn compress_file_in_memory(file: File) -> OuchResult<Vec<u8>> {
let file_contents = match file.contents_in_memory {
Some(bytes) => bytes,
None => {
unreachable!();
}
};
Ok(Self::compress_bytes(file_contents)?)
}
pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> OuchResult<Vec<u8>> {
let buffer = vec![];
let mut encoder = flate2::write::GzEncoder::new(
buffer,
flate2::Compression::default(),
);
encoder.write_all(&*bytes_to_compress)?;
Ok(encoder.finish()?)
}
}
impl Compressor for GzipCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
let format = CompressionFormat::Gzip;
match from {
Entry::Files(files) => Ok(
Self::compress_files(files, format)?
),
Entry::InMemory(file) => Ok(
Self::compress_file_in_memory(file)?
),
}
}
}

69
src/compressors/lzma.rs Normal file
View File

@ -0,0 +1,69 @@
use std::{fs, io::Write, 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 LzmaCompressor {}
impl LzmaCompressor {
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 path = &files[0];
ensure_exists(path)?;
let bytes = {
let bytes = fs::read(path)?;
Self::compress_bytes(bytes)?
};
println!(
"{}: compressed {:?} into memory ({} bytes)",
"info".yellow(),
&path,
bytes.len()
);
Ok(bytes)
}
pub fn compress_file_in_memory(file: File) -> OuchResult<Vec<u8>> {
let file_contents = match file.contents_in_memory {
Some(bytes) => bytes,
None => {
unreachable!();
}
};
Ok(Self::compress_bytes(file_contents)?)
}
pub fn compress_bytes(bytes_to_compress: Vec<u8>) -> OuchResult<Vec<u8>> {
let buffer = vec![];
let mut encoder = xz2::write::XzEncoder::new(buffer, 6);
encoder.write_all(&*bytes_to_compress)?;
Ok(encoder.finish()?)
}
}
impl Compressor for LzmaCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
let format = CompressionFormat::Lzma;
match from {
Entry::Files(files) => Ok(
Self::compress_files(files, format)?
),
Entry::InMemory(file) => Ok(
Self::compress_file_in_memory(file)?
),
}
}
}

View File

@ -1,7 +1,8 @@
mod tar;
mod zip;
mod bzip;
mod tomemory;
mod gzip;
mod lzma;
mod compressor;
pub use compressor::Compressor;
@ -9,5 +10,5 @@ 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;
pub use self::tomemory::LzmaCompressor;
pub use self::gzip::GzipCompressor;
pub use self::lzma::LzmaCompressor;

View File

@ -1,7 +1,7 @@
use std::{fs, path::PathBuf};
use colored::Colorize;
use tar::{Builder, EntryType, Header};
use tar::Builder;
use walkdir::WalkDir;
use crate::{compressors::Compressor, error::{Error, OuchResult}, file::File};
@ -15,7 +15,7 @@ impl TarCompressor {
// TODO: this function does not seem to be working correctly ;/
fn make_archive_from_memory(input: File) -> OuchResult<Vec<u8>> {
let contents = match input.contents_in_memory {
let _contents = match input.contents_in_memory {
Some(bytes) => bytes,
None => {
eprintln!("{}: reached TarCompressor::make_archive_from_memory without known content.", "internal error".red());

View File

@ -1,114 +0,0 @@
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 {}
pub struct LzmaCompressor {}
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(),
)),
CompressionFormat::Lzma => Box::new(xz2::write::XzEncoder::new(buffer, 6)),
_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)?
),
}
}
}
impl Compressor for LzmaCompressor {
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
let format = CompressionFormat::Lzma;
match from {
Entry::Files(files) => Ok(
CompressorToMemory::compress_files(files, format)?
),
Entry::InMemory(file) => Ok(
CompressorToMemory::compress_file_in_memory(file, format)?
),
}
}
}