ed_journals/modules/galaxy/models/
atmosphere.rs1use 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", "", ];
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}