deep_unpack/formats/
kinds.rs

1//! Supported archive formats
2use std::path::Path;
3
4use anyhow::Result;
5use lazy_static::lazy_static;
6use regex::Regex;
7
8use crate::formats::zip::ZipArchive;
9
10lazy_static! {
11    static ref BY_PATTERN: Vec<(Regex, ArchiveKind)> = vec![
12        (Regex::new(r"(?i)\.zip$").unwrap(), ArchiveKind::Zip),
13        (Regex::new(r"(?i)\.jar$").unwrap(), ArchiveKind::Zip)
14    ];
15}
16
17#[derive(Debug, Copy, Clone, PartialEq, Eq)]
18pub enum ArchiveKind {
19    Zip,
20}
21
22pub trait Archive {
23    fn path(&self) -> &Path;
24
25    fn unpack(&mut self, path: &Path) -> Result<()>;
26}
27
28impl ArchiveKind {
29    /// Check if the given file path is a supported archive type
30    #[must_use]
31    pub fn for_path(path: &Path) -> Option<Self> {
32        Self::determine_by_filename(path)
33    }
34
35    /// determine by file name if the path is an archive file
36    fn determine_by_filename(path: &Path) -> Option<Self> {
37        if let Some(filename) = path.file_name().and_then(std::ffi::OsStr::to_str) {
38            for &(ref regex, ty) in BY_PATTERN.iter() {
39                if regex.is_match(filename) {
40                    return Some(ty);
41                }
42            }
43        };
44        None
45    }
46
47    // create a new archive trait
48    #[allow(clippy::new_ret_no_self)]
49    #[must_use]
50    pub fn new(self, path: &Path) -> Box<dyn Archive> {
51        match self {
52            Self::Zip => Box::new(ZipArchive::new(path)),
53        }
54    }
55}