alpm_types/
compression.rs1use std::{
4 path::{Path, PathBuf},
5 str::FromStr,
6};
7
8use alpm_parsers::prelude::*;
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11use strum::{AsRefStr, Display, EnumString, IntoStaticStr, VariantNames};
12use winnow::{ascii::alphanumeric1, error::ErrMode};
13
14#[derive(
22 AsRefStr,
23 Clone,
24 Copy,
25 Debug,
26 Default,
27 Display,
28 EnumString,
29 Eq,
30 IntoStaticStr,
31 PartialEq,
32 VariantNames,
33)]
34#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
35pub enum CompressionAlgorithmFileExtension {
36 #[cfg_attr(feature = "serde", serde(rename = "Z"))]
40 #[strum(to_string = "Z")]
41 Compress,
42
43 #[cfg_attr(feature = "serde", serde(rename = "bz2"))]
47 #[strum(to_string = "bz2")]
48 Bzip2,
49
50 #[cfg_attr(feature = "serde", serde(rename = "gz"))]
54 #[strum(to_string = "gz")]
55 Gzip,
56
57 #[cfg_attr(feature = "serde", serde(rename = "lrz"))]
61 #[strum(to_string = "lrz")]
62 Lrzip,
63
64 #[cfg_attr(feature = "serde", serde(rename = "lz"))]
68 #[strum(to_string = "lz")]
69 Lzip,
70
71 #[cfg_attr(feature = "serde", serde(rename = "lz4"))]
75 #[strum(to_string = "lz4")]
76 Lz4,
77
78 #[cfg_attr(feature = "serde", serde(rename = "lzo"))]
82 #[strum(to_string = "lzo")]
83 Lzop,
84
85 #[cfg_attr(feature = "serde", serde(rename = "xz"))]
89 #[strum(to_string = "xz")]
90 Xz,
91
92 #[default]
96 #[cfg_attr(feature = "serde", serde(rename = "zst"))]
97 #[strum(to_string = "zst")]
98 Zstd,
99}
100
101impl AlpmParser for CompressionAlgorithmFileExtension {
102 fn parser<'a>(input: &mut Input<'a>) -> PResult<'a, Self> {
109 alphanumeric1
110 .try_map(CompressionAlgorithmFileExtension::from_str)
111 .expected_strings(CompressionAlgorithmFileExtension::VARIANTS)
112 .layer("compression algorithm file extension")
113 .parse_next(input)
114 }
115
116 fn delimiter_error_context<'a, O, P>(
117 parser: P,
118 ) -> impl Parser<Input<'a>, O, ErrMode<ParseStack<'a>>>
119 where
120 P: Parser<Input<'a>, O, ErrMode<ParseStack<'a>>>,
121 {
122 parser
123 .expected_text("an alphanumeric string")
124 .expected_strings(CompressionAlgorithmFileExtension::VARIANTS)
125 .layer("compression algorithm file extension")
126 }
127}
128
129impl TryFrom<&Path> for CompressionAlgorithmFileExtension {
130 type Error = crate::Error;
131
132 fn try_from(path: &Path) -> Result<Self, Self::Error> {
140 path.extension()
141 .and_then(|ext| ext.to_str())
142 .and_then(|ext| Self::from_str(ext).ok())
143 .ok_or(strum::ParseError::VariantNotFound.into())
144 }
145}
146
147impl TryFrom<PathBuf> for CompressionAlgorithmFileExtension {
148 type Error = crate::Error;
149
150 fn try_from(path: PathBuf) -> Result<Self, Self::Error> {
160 path.as_path().try_into()
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use rstest::*;
167 use testresult::TestResult;
168
169 use super::*;
170
171 #[rstest]
172 #[case("Z", CompressionAlgorithmFileExtension::Compress)]
173 #[case("bz2", CompressionAlgorithmFileExtension::Bzip2)]
174 #[case("gz", CompressionAlgorithmFileExtension::Gzip)]
175 #[case("lrz", CompressionAlgorithmFileExtension::Lrzip)]
176 #[case("lz", CompressionAlgorithmFileExtension::Lzip)]
177 #[case("lz4", CompressionAlgorithmFileExtension::Lz4)]
178 #[case("lzo", CompressionAlgorithmFileExtension::Lzop)]
179 #[case("xz", CompressionAlgorithmFileExtension::Xz)]
180 #[case("zst", CompressionAlgorithmFileExtension::Zstd)]
181 fn compression_algorithm_file_extension_from_str(
182 #[case] input: &str,
183 #[case] expected: CompressionAlgorithmFileExtension,
184 ) -> TestResult {
185 let parsed = CompressionAlgorithmFileExtension::from_str(input)?;
186 assert_eq!(parsed, expected);
187
188 Ok(())
189 }
190
191 #[rstest]
192 #[case("archive.Z", CompressionAlgorithmFileExtension::Compress)]
193 #[case("data.bz2", CompressionAlgorithmFileExtension::Bzip2)]
194 #[case("doc.gz", CompressionAlgorithmFileExtension::Gzip)]
195 #[case("video.lrz", CompressionAlgorithmFileExtension::Lrzip)]
196 #[case("binary.lz", CompressionAlgorithmFileExtension::Lzip)]
197 #[case("dump.lz4", CompressionAlgorithmFileExtension::Lz4)]
198 #[case("image.lzo", CompressionAlgorithmFileExtension::Lzop)]
199 #[case("package.xz", CompressionAlgorithmFileExtension::Xz)]
200 #[case("/var/cache/repo.zst", CompressionAlgorithmFileExtension::Zstd)]
201 fn compression_algorithm_file_extension_try_from_path(
202 #[case] filename: &str,
203 #[case] expected: CompressionAlgorithmFileExtension,
204 ) -> testresult::TestResult {
205 let path = PathBuf::from(filename);
206 let parsed = CompressionAlgorithmFileExtension::try_from(path)?;
207 assert_eq!(parsed, expected);
208 Ok(())
209 }
210
211 #[rstest]
212 #[case("file.txt")]
213 #[case("unknown.abc")]
214 #[case("noext")]
215 fn invalid_compression_file_extension(#[case] filename: &str) {
216 let path = Path::new(filename);
217 let Err(crate::Error::InvalidVariant(_)) =
218 CompressionAlgorithmFileExtension::try_from(path)
219 else {
220 panic!("Expected an Error::InvalidVariant but succeeded instead");
221 };
222 }
223}