Skip to main content

use_molar_mass/
mass_contribution_set.rs

1use std::fmt;
2
3use crate::{ElementMassContribution, MolarMass, MolarMassValidationError};
4
5/// Ordered per-element molar-mass contributions.
6#[derive(Clone, Debug, Default, PartialEq)]
7pub struct MassContributionSet {
8    contributions: Vec<ElementMassContribution>,
9}
10
11impl MassContributionSet {
12    /// Creates an empty contribution set.
13    #[must_use]
14    pub const fn new() -> Self {
15        Self {
16            contributions: Vec::new(),
17        }
18    }
19
20    /// Creates a contribution set from validated contributions.
21    #[must_use]
22    pub fn from_contributions(
23        contributions: impl IntoIterator<Item = ElementMassContribution>,
24    ) -> Self {
25        Self {
26            contributions: contributions.into_iter().collect(),
27        }
28    }
29
30    /// Appends a contribution.
31    pub fn push(&mut self, contribution: ElementMassContribution) {
32        self.contributions.push(contribution);
33    }
34
35    /// Returns the contributions as a slice.
36    #[must_use]
37    pub fn as_slice(&self) -> &[ElementMassContribution] {
38        &self.contributions
39    }
40
41    /// Iterates over contributions in stored order.
42    pub fn iter(&self) -> impl Iterator<Item = &ElementMassContribution> {
43        self.contributions.iter()
44    }
45
46    /// Returns the number of contributions.
47    #[must_use]
48    pub fn len(&self) -> usize {
49        self.contributions.len()
50    }
51
52    /// Returns true when the contribution set is empty.
53    #[must_use]
54    pub fn is_empty(&self) -> bool {
55        self.contributions.is_empty()
56    }
57
58    /// Returns the total molar-mass value in grams per mole.
59    #[must_use]
60    pub fn total_mass_value(&self) -> f64 {
61        self.contributions
62            .iter()
63            .map(ElementMassContribution::total_mass_value)
64            .sum()
65    }
66
67    /// Returns the total as a molar mass value in grams per mole.
68    ///
69    /// # Errors
70    ///
71    /// Returns a molar-mass validation error if the total is not finite and positive.
72    pub fn molar_mass(&self) -> Result<MolarMass, MolarMassValidationError> {
73        MolarMass::grams_per_mole(self.total_mass_value())
74    }
75}
76
77impl fmt::Display for MassContributionSet {
78    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
79        for (index, contribution) in self.contributions.iter().enumerate() {
80            if index > 0 {
81                formatter.write_str(", ")?;
82            }
83
84            write!(formatter, "{contribution}")?;
85        }
86
87        Ok(())
88    }
89}