use_stoichiometry/
reaction_entry.rs1use std::fmt;
2
3use use_chemical_formula::ChemicalFormula;
4
5use crate::{
6 ReactionSide, StoichiometricCoefficient, StoichiometricTerm, StoichiometryValidationError,
7};
8
9#[derive(Clone, Debug, Eq, PartialEq)]
11pub struct ReactionEntry {
12 term: StoichiometricTerm,
13 side: ReactionSide,
14}
15
16impl ReactionEntry {
17 pub fn new(
24 coefficient: StoichiometricCoefficient,
25 formula: ChemicalFormula,
26 side: ReactionSide,
27 ) -> Result<Self, StoichiometryValidationError> {
28 Ok(Self {
29 term: StoichiometricTerm::new(coefficient, formula)?,
30 side,
31 })
32 }
33
34 pub fn from_value(
40 coefficient: u32,
41 formula: ChemicalFormula,
42 side: ReactionSide,
43 ) -> Result<Self, StoichiometryValidationError> {
44 Self::new(StoichiometricCoefficient::new(coefficient)?, formula, side)
45 }
46
47 #[must_use]
49 pub const fn coefficient(&self) -> StoichiometricCoefficient {
50 self.term.coefficient()
51 }
52
53 #[must_use]
55 pub const fn formula(&self) -> &ChemicalFormula {
56 self.term.formula()
57 }
58
59 #[must_use]
61 pub const fn side(&self) -> ReactionSide {
62 self.side
63 }
64
65 #[must_use]
67 pub const fn term(&self) -> &StoichiometricTerm {
68 &self.term
69 }
70
71 #[must_use]
73 pub fn into_parts(self) -> (StoichiometricCoefficient, ChemicalFormula, ReactionSide) {
74 let (coefficient, formula) = self.term.into_parts();
75 (coefficient, formula, self.side)
76 }
77}
78
79impl fmt::Display for ReactionEntry {
80 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
81 write!(formatter, "{}", self.term)
82 }
83}
84
85#[derive(Clone, Debug, Eq, PartialEq)]
87pub struct ReactantEntry(ReactionEntry);
88
89impl ReactantEntry {
90 pub fn new(
97 coefficient: StoichiometricCoefficient,
98 formula: ChemicalFormula,
99 ) -> Result<Self, StoichiometryValidationError> {
100 Ok(Self(ReactionEntry::new(
101 coefficient,
102 formula,
103 ReactionSide::Reactant,
104 )?))
105 }
106
107 pub fn from_entry(entry: ReactionEntry) -> Result<Self, StoichiometryValidationError> {
114 if entry.side().is_reactant() {
115 Ok(Self(entry))
116 } else {
117 Err(StoichiometryValidationError::ExpectedReactant)
118 }
119 }
120
121 #[must_use]
123 pub const fn as_entry(&self) -> &ReactionEntry {
124 &self.0
125 }
126
127 #[must_use]
129 pub fn into_entry(self) -> ReactionEntry {
130 self.0
131 }
132}
133
134impl fmt::Display for ReactantEntry {
135 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
136 write!(formatter, "{}", self.0)
137 }
138}
139
140#[derive(Clone, Debug, Eq, PartialEq)]
142pub struct ProductEntry(ReactionEntry);
143
144impl ProductEntry {
145 pub fn new(
152 coefficient: StoichiometricCoefficient,
153 formula: ChemicalFormula,
154 ) -> Result<Self, StoichiometryValidationError> {
155 Ok(Self(ReactionEntry::new(
156 coefficient,
157 formula,
158 ReactionSide::Product,
159 )?))
160 }
161
162 pub fn from_entry(entry: ReactionEntry) -> Result<Self, StoichiometryValidationError> {
169 if entry.side().is_product() {
170 Ok(Self(entry))
171 } else {
172 Err(StoichiometryValidationError::ExpectedProduct)
173 }
174 }
175
176 #[must_use]
178 pub const fn as_entry(&self) -> &ReactionEntry {
179 &self.0
180 }
181
182 #[must_use]
184 pub fn into_entry(self) -> ReactionEntry {
185 self.0
186 }
187}
188
189impl fmt::Display for ProductEntry {
190 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
191 write!(formatter, "{}", self.0)
192 }
193}