Skip to main content

use_molar_mass/
element_mass_contribution.rs

1use std::fmt;
2
3use crate::atomic_mass_entry::validate_atomic_mass;
4use crate::atomic_mass_lookup::validate_symbol;
5use crate::{MolarMass, MolarMassValidationError};
6
7/// A per-element contribution to a formula molar mass.
8#[derive(Clone, Debug, PartialEq)]
9pub struct ElementMassContribution {
10    symbol: String,
11    atomic_mass: f64,
12    count: u32,
13}
14
15impl ElementMassContribution {
16    /// Creates an element mass contribution.
17    ///
18    /// # Errors
19    ///
20    /// Returns a molar-mass validation error when the symbol, atomic mass, count,
21    /// or calculated contribution is invalid.
22    pub fn new(
23        symbol: &str,
24        atomic_mass: f64,
25        count: u32,
26    ) -> Result<Self, MolarMassValidationError> {
27        let symbol = validate_symbol(symbol)?;
28        validate_atomic_mass(symbol, atomic_mass)?;
29
30        if count == 0 {
31            return Err(MolarMassValidationError::ZeroElementCount {
32                symbol: symbol.to_owned(),
33            });
34        }
35
36        let contribution = atomic_mass * f64::from(count);
37        MolarMass::grams_per_mole(contribution)?;
38
39        Ok(Self {
40            symbol: symbol.to_owned(),
41            atomic_mass,
42            count,
43        })
44    }
45
46    /// Returns the element symbol.
47    #[must_use]
48    pub fn symbol(&self) -> &str {
49        &self.symbol
50    }
51
52    /// Returns the atomic mass in grams per mole.
53    #[must_use]
54    pub const fn atomic_mass(&self) -> f64 {
55        self.atomic_mass
56    }
57
58    /// Returns the element count in the formula.
59    #[must_use]
60    pub const fn count(&self) -> u32 {
61        self.count
62    }
63
64    /// Returns the contribution value in grams per mole.
65    #[must_use]
66    pub fn total_mass_value(&self) -> f64 {
67        self.atomic_mass * f64::from(self.count)
68    }
69
70    /// Returns the contribution as a molar mass value in grams per mole.
71    ///
72    /// # Errors
73    ///
74    /// Returns a molar-mass validation error if the calculated contribution is invalid.
75    pub fn total_molar_mass(&self) -> Result<MolarMass, MolarMassValidationError> {
76        MolarMass::grams_per_mole(self.total_mass_value())
77    }
78}
79
80impl fmt::Display for ElementMassContribution {
81    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
82        write!(
83            formatter,
84            "{}: {} × {} = {} g/mol",
85            self.symbol,
86            self.count,
87            self.atomic_mass,
88            self.total_mass_value()
89        )
90    }
91}