Skip to main content

use_density/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4//! Density, mass, and volume helpers.
5
6use core::fmt;
7
8pub mod prelude;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum DensityError {
12    NonPositiveVolume,
13    NonPositiveDensity,
14}
15
16impl fmt::Display for DensityError {
17    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
18        match self {
19            Self::NonPositiveVolume => formatter.write_str("volume must be greater than zero"),
20            Self::NonPositiveDensity => formatter.write_str("density must be greater than zero"),
21        }
22    }
23}
24
25impl std::error::Error for DensityError {}
26
27#[must_use]
28pub const fn mass(density: f64, volume: f64) -> f64 {
29    density * volume
30}
31
32/// Computes density from mass and occupied volume.
33///
34/// # Errors
35///
36/// Returns [`DensityError::NonPositiveVolume`] when `volume` is less than or equal to zero.
37pub fn density(mass: f64, volume: f64) -> Result<f64, DensityError> {
38    if volume <= 0.0 {
39        Err(DensityError::NonPositiveVolume)
40    } else {
41        Ok(mass / volume)
42    }
43}
44
45/// Computes occupied volume from mass and density.
46///
47/// # Errors
48///
49/// Returns [`DensityError::NonPositiveDensity`] when `density` is less than or equal to zero.
50pub fn volume(mass: f64, density: f64) -> Result<f64, DensityError> {
51    if density <= 0.0 {
52        Err(DensityError::NonPositiveDensity)
53    } else {
54        Ok(mass / density)
55    }
56}
57
58#[cfg(test)]
59#[allow(clippy::float_cmp)]
60mod tests {
61    use super::{DensityError, density, mass, volume};
62
63    #[test]
64    fn density_helpers_cover_mass_volume_relationships() -> Result<(), DensityError> {
65        assert_eq!(density(10.0, 2.0)?, 5.0);
66        assert_eq!(mass(5.0, 2.0), 10.0);
67        assert_eq!(volume(10.0, 5.0)?, 2.0);
68        Ok(())
69    }
70
71    #[test]
72    fn density_validation_requires_positive_inputs() {
73        assert_eq!(density(10.0, 0.0), Err(DensityError::NonPositiveVolume));
74        assert_eq!(volume(10.0, 0.0), Err(DensityError::NonPositiveDensity));
75    }
76}