Skip to main content

ed_journals/modules/galaxy/models/
atmosphere.rs

1use std::str::FromStr;
2
3use lazy_static::lazy_static;
4use regex::Regex;
5use serde::Serialize;
6use thiserror::Error;
7
8use crate::from_str_deserialize_impl;
9use crate::galaxy::models::atmosphere_type::AtmosphereTypeError;
10use crate::modules::galaxy::AtmosphereType;
11
12#[derive(Debug, Serialize, Clone, PartialEq, Eq, Hash)]
13pub struct Atmosphere {
14    pub hot: bool,
15    pub density: AtmosphereDensity,
16    pub kind: AtmosphereType,
17}
18
19#[derive(Debug, Serialize, Clone, PartialEq, Eq, Hash)]
20pub enum AtmosphereDensity {
21    Thick,
22    Normal,
23    Thin,
24}
25
26#[derive(Debug, Error)]
27pub enum AtmosphereError {
28    #[error(transparent)]
29    UnknownAtmosphereType(AtmosphereTypeError),
30
31    #[error("Failed to parse atmosphere: '{0}'")]
32    FailedToParse(String),
33}
34
35lazy_static! {
36    static ref ATMOSPHERE_REGEX: Regex =
37        Regex::new(r#"^([hH]ot )?(([tT]hin|[tT]hick) )?([a-zA-Z -]+?)?( atmosphere)?$"#).unwrap();
38}
39
40impl FromStr for Atmosphere {
41    type Err = AtmosphereError;
42
43    fn from_str(s: &str) -> Result<Self, Self::Err> {
44        if s.is_empty() {
45            return Ok(Atmosphere {
46                hot: false,
47                density: AtmosphereDensity::Normal,
48                kind: AtmosphereType::None,
49            });
50        }
51
52        let Some(captures) = ATMOSPHERE_REGEX.captures(s) else {
53            return Err(AtmosphereError::FailedToParse(s.to_string()));
54        };
55
56        let hot = captures.get(1).is_some();
57
58        let density = match captures.get(3) {
59            Some(capture) => match capture.as_str() {
60                "thin" | "Thin" => AtmosphereDensity::Thin,
61                "thick" | "Thick" => AtmosphereDensity::Thick,
62                _ => AtmosphereDensity::Normal,
63            },
64            None => AtmosphereDensity::Normal,
65        };
66
67        let kind = captures
68            .get(4)
69            .expect("Should have been captured already")
70            .as_str()
71            .parse()
72            .map_err(AtmosphereError::UnknownAtmosphereType)?;
73
74        Ok(Atmosphere { kind, hot, density })
75    }
76}
77
78from_str_deserialize_impl!(Atmosphere);
79
80#[cfg(test)]
81mod tests {
82    use crate::galaxy::Atmosphere;
83    use std::str::FromStr;
84
85    #[test]
86    fn atmosphere_test_cases_are_parsed_correctly() {
87        let test_cases = [
88            "argon rich atmosphere",
89            "nitrogen atmosphere",
90            "Thin Carbon dioxide-rich",
91            "None",
92            "thick  atmosphere", // Because of course this is in there
93            "",                  // WHY?!
94        ];
95
96        for case in test_cases {
97            let result = Atmosphere::from_str(case);
98
99            dbg!(&result);
100            assert!(result.is_ok());
101        }
102    }
103}