flatpak_rs/
archive.rs

1use serde::{Deserialize, Deserializer, Serializer};
2
3use lazy_static::lazy_static;
4use regex::Regex;
5
6lazy_static! {
7    static ref PROJECT_NAME_REGEX: Regex = Regex::new(r"([0-9a-zA-Z_-]+)-[0-9]+.[0-9]+.[0-9]+").unwrap();
8}
9
10pub const RPM: &str = "rpm";
11pub const TAR: &str = "tar";
12pub const TAR_GZIP: &str = "tar-gzip";
13pub const TAR_COMPRESS: &str = "tar-compress";
14pub const TAR_BZIP2: &str = "tar-bzip2";
15pub const TAR_LZIP: &str = "tar-lzip";
16pub const TAR_LZMA: &str = "tar-lzma";
17pub const TAR_LZOP: &str = "tar-lzop";
18pub const TAR_XZ: &str = "tar-xz";
19pub const ZIP: &str = "zip";
20pub const SEVENZIP: &str = "7z";
21
22#[derive(Clone)]
23#[derive(Deserialize)]
24#[derive(Debug)]
25#[derive(Hash)]
26#[derive(PartialEq)]
27pub enum FlatpakArchiveType {
28    Rpm,
29    Tar,
30    TarGzip,
31    TarCompress,
32    TarBzip2,
33    TarLzip,
34    TarLzma,
35    TarLzop,
36    TarXz,
37    Zip,
38    SevenZip,
39}
40
41impl Default for FlatpakArchiveType {
42    fn default() -> Self {
43        FlatpakArchiveType::Rpm
44    }
45}
46impl FlatpakArchiveType {
47    pub fn to_string(&self) -> String {
48        match &self {
49            FlatpakArchiveType::Rpm => RPM.to_string(),
50            FlatpakArchiveType::SevenZip => SEVENZIP.to_string(),
51            FlatpakArchiveType::Tar => TAR.to_string(),
52            FlatpakArchiveType::TarGzip => TAR_GZIP.to_string(),
53            FlatpakArchiveType::TarCompress => TAR_COMPRESS.to_string(),
54            FlatpakArchiveType::TarBzip2 => TAR_BZIP2.to_string(),
55            FlatpakArchiveType::TarLzip => TAR_LZIP.to_string(),
56            FlatpakArchiveType::TarLzma => TAR_LZMA.to_string(),
57            FlatpakArchiveType::TarLzop => TAR_LZOP.to_string(),
58            FlatpakArchiveType::TarXz => TAR_XZ.to_string(),
59            FlatpakArchiveType::Zip => ZIP.to_string(),
60        }
61    }
62    pub fn from_string(archive_type: &str) -> Result<FlatpakArchiveType, String> {
63        if archive_type == RPM {
64            return Ok(FlatpakArchiveType::Rpm);
65        }
66        if archive_type == SEVENZIP {
67            return Ok(FlatpakArchiveType::SevenZip);
68        }
69        if archive_type == ZIP {
70            return Ok(FlatpakArchiveType::Zip);
71        }
72        if archive_type == TAR {
73            return Ok(FlatpakArchiveType::Tar);
74        }
75        if archive_type == TAR_XZ {
76            return Ok(FlatpakArchiveType::TarXz);
77        }
78        if archive_type == TAR_LZOP {
79            return Ok(FlatpakArchiveType::TarLzop);
80        }
81        if archive_type == TAR_COMPRESS {
82            return Ok(FlatpakArchiveType::TarCompress);
83        }
84        if archive_type == TAR_BZIP2 {
85            return Ok(FlatpakArchiveType::TarBzip2);
86        }
87        if archive_type == TAR_GZIP {
88            return Ok(FlatpakArchiveType::TarGzip);
89        }
90        if archive_type == TAR_LZIP {
91            return Ok(FlatpakArchiveType::TarLzip);
92        }
93        if archive_type == TAR_LZMA {
94            return Ok(FlatpakArchiveType::TarLzma);
95        }
96        if archive_type == TAR_LZOP {
97            return Ok(FlatpakArchiveType::TarLzop);
98        }
99        Err(format!("Invalid archive type {}.", archive_type))
100    }
101
102    /// Detects the archive type from a path or a URL, using
103    /// the extension only.
104    pub fn from_path(path: &str) -> Option<FlatpakArchiveType> {
105        let path = path.to_lowercase();
106        if path.ends_with(".tar") {
107            return Some(FlatpakArchiveType::Tar);
108        }
109        if path.ends_with(".tar.gz") || path.ends_with(".tgz") || path.ends_with(".taz") {
110            return Some(FlatpakArchiveType::TarGzip);
111        }
112        if path.ends_with(".tar.z") || path.ends_with(".taz") {
113            return Some(FlatpakArchiveType::TarCompress);
114        }
115        if path.ends_with(".tar.bz2") || path.ends_with(".tz2") {
116            return Some(FlatpakArchiveType::TarBzip2);
117        }
118        if path.ends_with(".tbz2") || path.ends_with(".tbz") {
119            return Some(FlatpakArchiveType::TarBzip2);
120        }
121        if path.ends_with(".tar.lz") {
122            return Some(FlatpakArchiveType::TarLzip);
123        }
124        if path.ends_with(".tar.lzma") || path.ends_with(".tlz") {
125            return Some(FlatpakArchiveType::TarLzma);
126        }
127        if path.ends_with(".tar.lzo") {
128            return Some(FlatpakArchiveType::TarLzop);
129        }
130        if path.ends_with(".tar.xz") || path.ends_with(".txz") {
131            return Some(FlatpakArchiveType::TarXz);
132        }
133        if path.ends_with(".zip") {
134            return Some(FlatpakArchiveType::Zip);
135        }
136        if path.ends_with(".rpm") {
137            return Some(FlatpakArchiveType::Rpm);
138        }
139        if path.ends_with(".7z") {
140            return Some(FlatpakArchiveType::SevenZip);
141        }
142        None
143    }
144
145    pub fn serialize<S>(x: &Option<FlatpakArchiveType>, s: S) -> Result<S::Ok, S::Error>
146    where
147        S: Serializer,
148    {
149        if let Some(build_system) = x {
150            return s.serialize_str(&build_system.to_string());
151        }
152        panic!("This should not happen.");
153    }
154
155    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<FlatpakArchiveType>, D::Error>
156    where
157        D: Deserializer<'de>,
158    {
159        let buf = String::deserialize(deserializer)?;
160
161        match FlatpakArchiveType::from_string(&buf) {
162            Ok(b) => Ok(Some(b)),
163            Err(e) => Err(e).map_err(serde::de::Error::custom),
164        }
165    }
166}
167
168///```
169///let project_name = flatpak_rs::archive::get_project_name_from_url(
170///  "https://download-fallback.gnome.org/sources/libgda/5.2/libgda-5.2.9.tar.xz"
171///);
172///assert!(project_name.is_some());
173///assert_eq!(project_name.unwrap(), "libgda");
174///
175///let project_name = flatpak_rs::archive::get_project_name_from_url(
176///  "https://download.gnome.org/core/3.28/3.28.2/sources/libgsf-1.14.43.tar.xz"
177///);
178///assert!(project_name.is_some());
179///assert_eq!(project_name.unwrap(), "libgsf");
180///```
181pub fn get_project_name_from_url(archive_url: &str) -> Option<String> {
182    let archive_filename = archive_url.split("/").last().unwrap();
183    let captured_groups = match PROJECT_NAME_REGEX.captures(archive_filename) {
184        Some(g) => g,
185        None => return None,
186    };
187    if captured_groups.len() == 0 {
188        return None;
189    }
190    return Some(captured_groups[1].to_string());
191}