use_chemical_formula/
formula_group.rs1use std::collections::BTreeMap;
2use std::fmt;
3
4use crate::{FormulaMultiplier, FormulaTerm, FormulaValidationError};
5
6#[derive(Clone, Debug, Eq, PartialEq)]
8pub struct FormulaGroup {
9 terms: Vec<FormulaTerm>,
10 multiplier: FormulaMultiplier,
11}
12
13impl FormulaGroup {
14 pub fn new(
20 terms: Vec<FormulaTerm>,
21 multiplier: FormulaMultiplier,
22 ) -> Result<Self, FormulaValidationError> {
23 if terms.is_empty() {
24 Err(FormulaValidationError::EmptyGroup)
25 } else {
26 Ok(Self { terms, multiplier })
27 }
28 }
29
30 #[must_use]
32 pub fn terms(&self) -> &[FormulaTerm] {
33 &self.terms
34 }
35
36 #[must_use]
38 pub const fn multiplier(&self) -> FormulaMultiplier {
39 self.multiplier
40 }
41
42 pub(crate) fn add_counts(&self, counts: &mut BTreeMap<String, u64>, multiplier: u64) {
43 let combined_multiplier = multiplier.saturating_mul(u64::from(self.multiplier.get()));
44 for term in &self.terms {
45 term.add_counts(counts, combined_multiplier);
46 }
47 }
48}
49
50impl fmt::Display for FormulaGroup {
51 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
52 formatter.write_str("(")?;
53 for term in &self.terms {
54 write!(formatter, "{term}")?;
55 }
56 formatter.write_str(")")?;
57 if !self.multiplier.is_one() {
58 write!(formatter, "{}", self.multiplier)?;
59 }
60 Ok(())
61 }
62}