vers 0.5.0

Install and manage dev tools with multiple environments
Documentation
use self::{gzip::GzipArchiver, tar::TarArchiver, tar_gzip::TarGzipArchiver, zip::ZipArchiver};
use async_trait::async_trait;
use std::path::{Path, PathBuf};
use thiserror::Error;

mod gzip;
mod tar;
mod tar_gzip;
mod zip;

#[derive(Debug, Error)]
pub enum ArchiverError {
    #[error("IO Error accessing {file_path}. {source:?}")]
    IoError {
        file_path: PathBuf,
        source: std::io::Error,
    },
    #[error("Extractor({extractor}) was unable to load '{file_path}'. {message}")]
    ExtractorLoadError {
        extractor: String,
        file_path: PathBuf,
        message: String,
    },
    #[error("Extractor({extractor}) encountered an error {message}")]
    ExtractorError { extractor: String, message: String },
    #[error("Unable to create directory {file_path}. {source:?}")]
    DirectorCreateError {
        file_path: PathBuf,
        source: std::io::Error,
    },
    #[error("Failed to create file {file_path}. {source:?}")]
    FileCreateError {
        file_path: PathBuf,
        source: std::io::Error,
    },
}

type Result<T, E = ArchiverError> = std::result::Result<T, E>;

#[async_trait]
pub trait Archiver {
    async fn extract_to(&self, file_path: &'_ Path, out_dir: &'_ Path) -> Result<()>;
    async fn extract(&self, file_path: &'_ Path) -> Result<()>;
    fn can_handle(&self, file_path: &'_ Path) -> bool;
    fn name(&self) -> &'static str;
}

pub fn determine_possible_extractors(file_path: &'_ Path) -> Vec<Box<dyn Archiver>> {
    let possible_extractors: Vec<Box<dyn Archiver>> = vec![
        Box::new(TarGzipArchiver),
        Box::new(TarArchiver),
        Box::new(ZipArchiver),
        Box::new(GzipArchiver),
    ];

    possible_extractors
        .into_iter()
        .filter(|e| e.can_handle(file_path))
        .collect()
}

pub async fn handle_file_extraction(
    archiver: Box<dyn Archiver>,
    input_file: &'_ Path,
    output_dir: Option<PathBuf>,
) -> Result<()> {
    if let Some(out_dir) = output_dir {
        archiver.extract_to(input_file, &out_dir).await
    } else {
        archiver.extract(input_file).await
    }
}