pub trait Decompressor {
fn decompress(file: &str, path: &str) -> Result<(), String>;
}
pub enum DecompressionMethod {
#[cfg(feature = "gzip")]
TarGzip,
#[cfg(feature = "normal_zip")]
Zip,
}
impl DecompressionMethod {
pub fn decompress(&self, file: &str, path: &str) -> Result<(), String> {
match self {
#[cfg(feature = "gzip")]
DecompressionMethod::TarGzip => gzip::TarGzipDecompressor::decompress(file, path),
#[cfg(feature = "normal_zip")]
DecompressionMethod::Zip => zip::ZipDecompressor::decompress(file, path),
}
}
}
#[cfg(feature = "gzip")]
mod gzip {
use std::fs::File;
use super::Decompressor;
use flate2::read::GzDecoder;
use tar::Archive;
pub struct TarGzipDecompressor;
impl Decompressor for TarGzipDecompressor {
fn decompress(file: &str, path: &str) -> Result<(), String> {
let tar_gz = File::open(file).expect("Failed to open archive");
let tar = GzDecoder::new(tar_gz);
let mut archive = Archive::new(tar);
archive.unpack(path).expect("Failed to extract archive");
Ok(())
}
}
}
#[cfg(feature = "normal_zip")]
mod zip {
use std::fs::{File, create_dir_all};
use std::io;
use std::path::Path;
use zip::ZipArchive;
use super::Decompressor;
pub struct ZipDecompressor;
impl Decompressor for ZipDecompressor {
fn decompress(file: &str, path: &str) -> Result<(), String> {
let file = File::open(file).expect("Failed to open archive");
let mut archive = ZipArchive::new(file).expect("Failed to open archive");
create_dir_all(path).expect("Failed to create directory");
for i in 0..archive.len() {
let mut file = archive.by_index(i).expect("Failed to extract file");
let outpath = Path::new(path).join(file.mangled_name());
if file.name().ends_with('/') {
create_dir_all(&outpath).expect("Failed to create directory");
} else {
if let Some(p) = outpath.parent() {
if !p.exists() {
create_dir_all(p).expect("Failed to create directory");
}
}
let mut outfile = File::create(&outpath).expect("Failed to create file");
io::copy(&mut file, &mut outfile).expect("Failed to copy file");
}
}
Ok(())
}
}
}
pub struct DLDecompressionConfig {
pub method: DecompressionMethod,
pub output: String,
pub delete_after: bool,
}
impl DLDecompressionConfig {
pub fn new(method: DecompressionMethod, output: &str) -> Self {
DLDecompressionConfig {
method,
output: output.to_string(),
delete_after: true,
}
}
pub fn with_method(mut self, method: DecompressionMethod) -> Self {
self.method = method;
self
}
pub fn with_output(mut self, output: String) -> Self {
self.output = output;
self
}
pub fn with_delete_after(mut self, delete_after: bool) -> Self {
self.delete_after = delete_after;
self
}
pub fn delete_after(mut self) -> Self {
self.delete_after = true;
self
}
pub fn decompress(&self, file: &str) -> Result<(), String> {
self.method.decompress(file, &self.output)?;
Ok(())
}
}