use_molar_mass/
atomic_mass_entry.rs1use std::fmt;
2
3use use_chemical_formula::is_valid_element_symbol;
4
5use crate::MolarMassValidationError;
6
7#[derive(Clone, Debug, PartialEq)]
9pub struct AtomicMassEntry {
10 symbol: String,
11 atomic_mass: f64,
12}
13
14impl AtomicMassEntry {
15 pub fn new(symbol: &str, atomic_mass: f64) -> Result<Self, MolarMassValidationError> {
23 let symbol = symbol.trim();
24
25 if !is_valid_element_symbol(symbol) {
26 return Err(MolarMassValidationError::InvalidElementSymbol(
27 symbol.to_owned(),
28 ));
29 }
30
31 validate_atomic_mass(symbol, atomic_mass)?;
32
33 Ok(Self {
34 symbol: symbol.to_owned(),
35 atomic_mass,
36 })
37 }
38
39 pub(crate) fn from_validated(symbol: String, atomic_mass: f64) -> Self {
40 Self {
41 symbol,
42 atomic_mass,
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
59impl TryFrom<(&str, f64)> for AtomicMassEntry {
60 type Error = MolarMassValidationError;
61
62 fn try_from(value: (&str, f64)) -> Result<Self, Self::Error> {
63 Self::new(value.0, value.1)
64 }
65}
66
67impl fmt::Display for AtomicMassEntry {
68 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
69 write!(formatter, "{}: {} g/mol", self.symbol, self.atomic_mass)
70 }
71}
72
73pub(crate) fn validate_atomic_mass(
74 symbol: &str,
75 atomic_mass: f64,
76) -> Result<(), MolarMassValidationError> {
77 if !atomic_mass.is_finite() {
78 Err(MolarMassValidationError::NonFiniteAtomicMass {
79 symbol: symbol.to_owned(),
80 })
81 } else if atomic_mass <= 0.0 {
82 Err(MolarMassValidationError::NonPositiveAtomicMass {
83 symbol: symbol.to_owned(),
84 })
85 } else {
86 Ok(())
87 }
88}