Skip to main content

use_molar_mass/
molar_mass.rs

1use std::fmt;
2
3use crate::{MolarMassUnit, MolarMassValidationError};
4
5/// A positive finite molar mass value with an associated display unit.
6#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
7pub struct MolarMass {
8    value: f64,
9    unit: MolarMassUnit,
10}
11
12impl MolarMass {
13    /// Creates a molar mass value in the requested unit.
14    ///
15    /// # Errors
16    ///
17    /// Returns [`MolarMassValidationError::NonFiniteMolarMass`] when `value` is
18    /// not finite, or [`MolarMassValidationError::NonPositiveMolarMass`] when it
19    /// is zero or negative.
20    pub fn new(value: f64, unit: MolarMassUnit) -> Result<Self, MolarMassValidationError> {
21        validate_molar_mass(value)?;
22
23        Ok(Self { value, unit })
24    }
25
26    /// Creates a molar mass in grams per mole.
27    ///
28    /// # Errors
29    ///
30    /// Returns a molar-mass validation error when `value` is not finite and positive.
31    pub fn grams_per_mole(value: f64) -> Result<Self, MolarMassValidationError> {
32        Self::new(value, MolarMassUnit::GramsPerMole)
33    }
34
35    /// Creates a molar mass in kilograms per mole.
36    ///
37    /// # Errors
38    ///
39    /// Returns a molar-mass validation error when `value` is not finite and positive.
40    pub fn kilograms_per_mole(value: f64) -> Result<Self, MolarMassValidationError> {
41        Self::new(value, MolarMassUnit::KilogramsPerMole)
42    }
43
44    /// Returns the numeric molar mass value.
45    #[must_use]
46    pub const fn value(self) -> f64 {
47        self.value
48    }
49
50    /// Returns the molar mass display unit.
51    #[must_use]
52    pub const fn unit(self) -> MolarMassUnit {
53        self.unit
54    }
55}
56
57impl fmt::Display for MolarMass {
58    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
59        write!(formatter, "{} {}", self.value, self.unit)
60    }
61}
62
63fn validate_molar_mass(value: f64) -> Result<(), MolarMassValidationError> {
64    if !value.is_finite() {
65        Err(MolarMassValidationError::NonFiniteMolarMass)
66    } else if value <= 0.0 {
67        Err(MolarMassValidationError::NonPositiveMolarMass)
68    } else {
69        Ok(())
70    }
71}