x2y/
format.rs

1use std::fmt;
2use std::path::Path;
3
4use crate::error::X2YError;
5#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
6pub enum Format {
7    Yaml,
8    Json,
9    Toml,
10}
11
12impl TryFrom<&Path> for Format {
13    type Error = X2YError;
14
15    fn try_from(s: &Path) -> Result<Self, Self::Error> {
16        if let Some(extension) = s.extension() {
17            if let Some(format) = extension.to_str() {
18                match format.trim() {
19                    "yaml" => Ok(Self::Yaml),
20                    "yml" => Ok(Self::Yaml),
21                    "json" => Ok(Self::Json),
22                    "toml" => Ok(Self::Toml),
23                    other => Err(X2YError::InvalidInput(format!(
24                        "{} is not a supported file format.",
25                        other
26                    ))),
27                }
28            } else {
29                Err(X2YError::InvalidInput(format!(
30                    "{} contains invalid unicode.",
31                    s.display()
32                )))
33            }
34        } else if let Some(s) = s.to_str() {
35            match s.trim() {
36                "yaml" => Ok(Self::Yaml),
37                "yml" => Ok(Self::Yaml),
38                "json" => Ok(Self::Json),
39                "toml" => Ok(Self::Toml),
40                other => Err(X2YError::InvalidInput(format!(
41                    "{} is not a supported file format.",
42                    other
43                ))),
44            }
45        } else {
46            Err(X2YError::InvalidInput(format!(
47                "{:?} has no retrievable extension.",
48                s
49            )))
50        }
51    }
52}
53
54impl fmt::Display for Format {
55    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56        match self {
57            Format::Yaml => write!(f, "yaml"),
58            Format::Json => write!(f, "json"),
59            Format::Toml => write!(f, "toml"),
60        }
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use std::path::PathBuf;
68
69    use claims::*;
70
71    #[test]
72    fn a_format_is_extracted_from_a_path() {
73        let input = PathBuf::from("directory/test.yaml");
74        let path = input.as_path();
75        let format = Format::try_from(path).unwrap();
76        assert_eq!(Format::Yaml, format);
77    }
78
79    #[test]
80    fn a_path_containing_an_unsupported_file_format_is_not_extracted() {
81        let input = PathBuf::from("directory/test.cpp");
82        let path = input.as_path();
83        let format = Format::try_from(path);
84        assert_err!(format);
85    }
86
87    #[test]
88    fn a_path_of_just_a_file_format_is_extracted() {
89        let input = PathBuf::from("yaml");
90        let path = input.as_path();
91        let format = Format::try_from(path).unwrap();
92        assert_eq!(Format::Yaml, format);
93    }
94    #[test]
95    fn a_path_containing_format_names_is_ok() {
96        let input = PathBuf::from("json_yaml.yaml");
97        let path = input.as_path();
98        let format = Format::try_from(path).unwrap();
99        assert_eq!(Format::Yaml, format);
100    }
101}