use_molar_mass/
element_mass_contribution.rs1use std::fmt;
2
3use crate::atomic_mass_entry::validate_atomic_mass;
4use crate::atomic_mass_lookup::validate_symbol;
5use crate::{MolarMass, MolarMassValidationError};
6
7#[derive(Clone, Debug, PartialEq)]
9pub struct ElementMassContribution {
10 symbol: String,
11 atomic_mass: f64,
12 count: u32,
13}
14
15impl ElementMassContribution {
16 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 #[must_use]
48 pub fn symbol(&self) -> &str {
49 &self.symbol
50 }
51
52 #[must_use]
54 pub const fn atomic_mass(&self) -> f64 {
55 self.atomic_mass
56 }
57
58 #[must_use]
60 pub const fn count(&self) -> u32 {
61 self.count
62 }
63
64 #[must_use]
66 pub fn total_mass_value(&self) -> f64 {
67 self.atomic_mass * f64::from(self.count)
68 }
69
70 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}