ed_journals/modules/galaxy/models/
volcanism.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::modules::galaxy::VolcanismType;
10
11#[derive(Debug, Serialize, Clone, PartialEq)]
12pub struct Volcanism {
13 pub kind: VolcanismType,
14 pub classification: VolcanismClassification,
15}
16
17#[derive(Debug, Serialize, Clone, PartialEq)]
18pub enum VolcanismClassification {
19 Minor,
20 Normal,
21 Major,
22}
23
24#[derive(Debug, Error)]
25pub enum VolcanismError {
26 #[error("Unknown volcanism type: {0}")]
27 UnknownVolcanismType(#[source] serde_json::Error),
28
29 #[error("Failed to parse volcanism: '{0}'")]
30 FailedToParse(String),
31}
32
33lazy_static! {
34 static ref VOLCANISM_REGEX: Regex =
35 Regex::new("(^[mM]inor |^[mM]ajor |^)([a-zA-Z ]+?)( volcanism)?$").unwrap();
36}
37
38impl FromStr for Volcanism {
39 type Err = VolcanismError;
40
41 fn from_str(s: &str) -> Result<Self, Self::Err> {
42 if s.is_empty() {
45 return Ok(Volcanism {
46 kind: VolcanismType::None,
47 classification: VolcanismClassification::Normal,
48 });
49 }
50
51 let Some(captures) = VOLCANISM_REGEX.captures(s) else {
52 return Err(VolcanismError::FailedToParse(s.to_string()));
53 };
54
55 let kind = captures
56 .get(2)
57 .expect("Should have been captured already")
58 .as_str()
59 .parse()
60 .map_err(VolcanismError::UnknownVolcanismType)?;
61
62 let classification = match captures
63 .get(1)
64 .expect("Should have been captured already")
65 .as_str()
66 {
67 "minor " | "Minor " => VolcanismClassification::Minor,
68 "major " | "Major " => VolcanismClassification::Major,
69 _ => VolcanismClassification::Normal,
70 };
71
72 Ok(Volcanism {
73 kind,
74 classification,
75 })
76 }
77}
78
79from_str_deserialize_impl!(Volcanism);
80
81#[cfg(test)]
82mod tests {
83 use std::str::FromStr;
84
85 use crate::modules::galaxy::{Volcanism, VolcanismClassification, VolcanismType};
86
87 #[test]
88 fn volcanism_test_cases_are_parsed_correctly() {
89 let test_cases = [
90 (
91 "minor silicate vapour geysers volcanism",
92 Volcanism {
93 kind: VolcanismType::SilicateVapourGeysers,
94 classification: VolcanismClassification::Minor,
95 },
96 ),
97 (
98 "major rocky magma volcanism",
99 Volcanism {
100 kind: VolcanismType::RockyMagma,
101 classification: VolcanismClassification::Major,
102 },
103 ),
104 (
105 "minor metallic magma volcanism",
106 Volcanism {
107 kind: VolcanismType::MetallicMagma,
108 classification: VolcanismClassification::Minor,
109 },
110 ),
111 ];
112
113 for (case, expected) in test_cases {
114 let result = Volcanism::from_str(case);
115
116 assert!(result.is_ok());
117 assert_eq!(result.unwrap(), expected);
118 }
119 }
120}