9 use CompressionFormat::*;
11 /// Represents the extension of a file, but only really caring about
12 /// compression formats (and .tar).
13 /// Ex.: Extension::new("file.tar.gz") == Extension { first_ext: Some(Tar), second_ext: Gzip }
14 #[derive(Clone, Debug, PartialEq, Eq)]
15 pub struct Extension {
16 pub first_ext: Option<CompressionFormat>,
17 pub second_ext: CompressionFormat,
20 pub fn get_extension_from_filename(filename: &str) -> Option<(&str, &str)> {
21 let path = Path::new(filename);
23 let ext = path.extension().and_then(OsStr::to_str)?;
25 let previous_extension = path
27 .and_then(OsStr::to_str)
28 .and_then(get_extension_from_filename);
30 if let Some((_, prev)) = previous_extension {
37 impl From<CompressionFormat> for Extension {
38 fn from(second_ext: CompressionFormat) -> Self {
47 pub fn new(filename: &str) -> error::OuchResult<Self> {
48 let ext_from_str = |ext| match ext {
52 "bz" | "bz2" => Ok(Bzip),
53 "xz" | "lz" | "lzma" => Ok(Lzma),
54 other => Err(error::Error::UnknownExtensionError(other.into())),
57 let (first_ext, second_ext) = match get_extension_from_filename(filename) {
58 Some(extension_tuple) => match extension_tuple {
59 ("", snd) => (None, snd),
60 (fst, snd) => (Some(fst), snd),
62 None => return Err(error::Error::MissingExtensionError(filename.into())),
65 let (first_ext, second_ext) = match (first_ext, second_ext) {
67 let ext = ext_from_str(snd)?;
71 let snd = ext_from_str(snd)?;
72 let fst = ext_from_str(fst).ok();
84 #[derive(Clone, PartialEq, Eq, Debug)]
85 /// Accepted extensions for input and output
86 pub enum CompressionFormat {
93 // .tar (technically not a compression extension, but will do for now)
99 fn extension_from_os_str(ext: &OsStr) -> Result<CompressionFormat, error::Error> {
100 // let ext = Path::new(ext);
102 let ext = match ext.to_str() {
104 None => return Err(error::Error::InvalidUnicode),
111 "bz" | "bz2" => Ok(Bzip),
112 "xz" | "lzma" | "lz" => Ok(Lzma),
113 other => Err(error::Error::UnknownExtensionError(other.into())),
117 impl TryFrom<&PathBuf> for CompressionFormat {
118 type Error = error::Error;
120 fn try_from(ext: &PathBuf) -> Result<Self, Self::Error> {
121 let ext = match ext.extension() {
124 return Err(error::Error::MissingExtensionError(String::new()));
127 extension_from_os_str(ext)
131 impl TryFrom<&str> for CompressionFormat {
132 type Error = error::Error;
134 fn try_from(filename: &str) -> Result<Self, Self::Error> {
135 let filename = Path::new(filename);
136 let ext = match filename.extension() {
138 None => return Err(error::Error::MissingExtensionError(String::new())),
141 extension_from_os_str(ext)
145 impl Display for CompressionFormat {
146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {