use_chemical_formula/
chemical_formula.rs1use std::collections::BTreeMap;
2use std::fmt;
3use std::str::FromStr;
4
5use crate::{FormulaParseError, FormulaPart, HydratePart, parse};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct ChemicalFormula {
10 main_part: FormulaPart,
11 hydrate_parts: Vec<HydratePart>,
12}
13
14impl ChemicalFormula {
15 #[must_use]
17 pub fn new(main_part: FormulaPart, hydrate_parts: Vec<HydratePart>) -> Self {
18 Self {
19 main_part,
20 hydrate_parts,
21 }
22 }
23
24 pub fn parse(input: &str) -> Result<Self, FormulaParseError> {
31 parse::parse_formula(input)
32 }
33
34 #[must_use]
36 pub const fn main_part(&self) -> &FormulaPart {
37 &self.main_part
38 }
39
40 #[must_use]
42 pub fn hydrate_parts(&self) -> &[HydratePart] {
43 &self.hydrate_parts
44 }
45
46 #[must_use]
48 pub fn element_counts(&self) -> BTreeMap<String, u64> {
49 let mut counts = BTreeMap::new();
50 self.main_part.add_counts(&mut counts, 1);
51 for hydrate_part in &self.hydrate_parts {
52 hydrate_part.add_counts(&mut counts);
53 }
54 counts
55 }
56}
57
58impl fmt::Display for ChemicalFormula {
59 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
60 write!(formatter, "{}", self.main_part)?;
61 for hydrate_part in &self.hydrate_parts {
62 write!(formatter, "ยท{hydrate_part}")?;
63 }
64 Ok(())
65 }
66}
67
68impl FromStr for ChemicalFormula {
69 type Err = FormulaParseError;
70
71 fn from_str(input: &str) -> Result<Self, Self::Err> {
72 Self::parse(input)
73 }
74}