Skip to main content

use_reaction/
reaction_term.rs

1use std::fmt;
2
3use use_chemical_formula::ChemicalFormula;
4use use_stoichiometry::{StoichiometricCoefficient, StoichiometricTerm};
5
6use crate::ReactionValidationError;
7
8/// A formula-backed reaction term with a stoichiometric coefficient.
9#[derive(Clone, Debug, Eq, PartialEq)]
10pub struct ReactionTerm {
11    term: StoichiometricTerm,
12}
13
14impl ReactionTerm {
15    /// Creates a reaction term with coefficient one.
16    #[must_use]
17    pub fn new(formula: ChemicalFormula) -> Self {
18        match Self::from_value(1, formula) {
19            Ok(term) => term,
20            Err(error) => unreachable!("coefficient one should be valid: {error}"),
21        }
22    }
23
24    /// Creates a reaction term from validated parts.
25    ///
26    /// # Errors
27    ///
28    /// Returns [`ReactionValidationError::InvalidStoichiometry`] if the stoichiometry primitive
29    /// rejects the coefficient.
30    pub fn from_parts(
31        coefficient: StoichiometricCoefficient,
32        formula: ChemicalFormula,
33    ) -> Result<Self, ReactionValidationError> {
34        Ok(Self {
35            term: StoichiometricTerm::new(coefficient, formula)?,
36        })
37    }
38
39    /// Creates a reaction term from a raw coefficient value.
40    ///
41    /// # Errors
42    ///
43    /// Returns [`ReactionValidationError::InvalidStoichiometry`] when `coefficient` is zero.
44    pub fn from_value(
45        coefficient: u32,
46        formula: ChemicalFormula,
47    ) -> Result<Self, ReactionValidationError> {
48        Self::from_parts(StoichiometricCoefficient::new(coefficient)?, formula)
49    }
50
51    /// Returns a copy of this term with a new coefficient.
52    ///
53    /// # Errors
54    ///
55    /// Returns [`ReactionValidationError::InvalidStoichiometry`] when `coefficient` is zero.
56    pub fn with_coefficient(self, coefficient: u32) -> Result<Self, ReactionValidationError> {
57        let (_, formula) = self.term.into_parts();
58        Self::from_value(coefficient, formula)
59    }
60
61    /// Returns the stoichiometric coefficient.
62    #[must_use]
63    pub const fn coefficient(&self) -> StoichiometricCoefficient {
64        self.term.coefficient()
65    }
66
67    /// Returns the chemical formula.
68    #[must_use]
69    pub const fn formula(&self) -> &ChemicalFormula {
70        self.term.formula()
71    }
72
73    /// Returns the wrapped stoichiometric term.
74    #[must_use]
75    pub const fn as_stoichiometric_term(&self) -> &StoichiometricTerm {
76        &self.term
77    }
78
79    /// Consumes this value and returns the wrapped stoichiometric term.
80    #[must_use]
81    pub fn into_stoichiometric_term(self) -> StoichiometricTerm {
82        self.term
83    }
84
85    /// Consumes the term and returns its parts.
86    #[must_use]
87    pub fn into_parts(self) -> (StoichiometricCoefficient, ChemicalFormula) {
88        self.term.into_parts()
89    }
90}
91
92impl From<StoichiometricTerm> for ReactionTerm {
93    fn from(term: StoichiometricTerm) -> Self {
94        Self { term }
95    }
96}
97
98impl fmt::Display for ReactionTerm {
99    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
100        write!(formatter, "{}", self.term)
101    }
102}