use_reaction/
reaction_condition.rs1use std::fmt;
2
3use crate::{Catalyst, ReactionValidationError, Solvent};
4
5#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
7pub enum ReactionCondition {
8 Temperature(String),
10 Pressure(String),
12 Catalyst(Catalyst),
14 Solvent(Solvent),
16 Heat,
18 Light,
20 Electrolysis,
22 Custom {
24 label: String,
26 value: Option<String>,
28 },
29}
30
31impl ReactionCondition {
32 pub fn temperature(label: &str) -> Result<Self, ReactionValidationError> {
39 let trimmed = label.trim();
40 if trimmed.is_empty() {
41 Err(ReactionValidationError::EmptyTemperatureLabel)
42 } else {
43 Ok(Self::Temperature(trimmed.to_owned()))
44 }
45 }
46
47 pub fn pressure(label: &str) -> Result<Self, ReactionValidationError> {
54 let trimmed = label.trim();
55 if trimmed.is_empty() {
56 Err(ReactionValidationError::EmptyPressureLabel)
57 } else {
58 Ok(Self::Pressure(trimmed.to_owned()))
59 }
60 }
61
62 pub fn catalyst(label: &str) -> Result<Self, ReactionValidationError> {
69 Ok(Self::Catalyst(Catalyst::new(label)?))
70 }
71
72 pub fn solvent(label: &str) -> Result<Self, ReactionValidationError> {
79 Ok(Self::Solvent(Solvent::new(label)?))
80 }
81
82 pub fn custom(label: &str, value: Option<&str>) -> Result<Self, ReactionValidationError> {
90 let label = label.trim();
91 if label.is_empty() {
92 return Err(ReactionValidationError::EmptyConditionLabel);
93 }
94
95 let value = value
96 .map(str::trim)
97 .map(|trimmed| {
98 if trimmed.is_empty() {
99 Err(ReactionValidationError::EmptyConditionValue)
100 } else {
101 Ok(trimmed.to_owned())
102 }
103 })
104 .transpose()?;
105
106 Ok(Self::Custom {
107 label: label.to_owned(),
108 value,
109 })
110 }
111
112 pub fn validate(&self) -> Result<(), ReactionValidationError> {
119 match self {
120 Self::Temperature(label) if label.trim().is_empty() => {
121 Err(ReactionValidationError::EmptyTemperatureLabel)
122 },
123 Self::Pressure(label) if label.trim().is_empty() => {
124 Err(ReactionValidationError::EmptyPressureLabel)
125 },
126 Self::Custom { label, .. } if label.trim().is_empty() => {
127 Err(ReactionValidationError::EmptyConditionLabel)
128 },
129 Self::Custom {
130 value: Some(value), ..
131 } if value.trim().is_empty() => Err(ReactionValidationError::EmptyConditionValue),
132 _ => Ok(()),
133 }
134 }
135}
136
137impl From<Catalyst> for ReactionCondition {
138 fn from(catalyst: Catalyst) -> Self {
139 Self::Catalyst(catalyst)
140 }
141}
142
143impl From<Solvent> for ReactionCondition {
144 fn from(solvent: Solvent) -> Self {
145 Self::Solvent(solvent)
146 }
147}
148
149impl fmt::Display for ReactionCondition {
150 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
151 match self {
152 Self::Temperature(label) => write!(formatter, "temperature: {label}"),
153 Self::Pressure(label) => write!(formatter, "pressure: {label}"),
154 Self::Catalyst(catalyst) => write!(formatter, "catalyst: {catalyst}"),
155 Self::Solvent(solvent) => write!(formatter, "solvent: {solvent}"),
156 Self::Heat => formatter.write_str("heat"),
157 Self::Light => formatter.write_str("light"),
158 Self::Electrolysis => formatter.write_str("electrolysis"),
159 Self::Custom { label, value } => match value {
160 Some(value) => write!(formatter, "{label}: {value}"),
161 None => formatter.write_str(label),
162 },
163 }
164 }
165}