use std::ops::Mul;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use super::{
constants, Density, DensityUnit, Mass, MassUnit, Measurement, PhysicalQuantity, UnitOfMeasure,
};
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(C)]
pub enum VolumeUnit {
CubicMeters,
Liter,
USGallon,
}
impl UnitOfMeasure<f32> for VolumeUnit {
fn quantity() -> PhysicalQuantity {
PhysicalQuantity::Volume
}
fn si() -> Self {
Self::CubicMeters
}
fn symbol(&self) -> &'static str {
match self {
Self::CubicMeters => "m³",
Self::Liter => "L",
Self::USGallon => "gal",
}
}
fn from_si(value: f32, to: &Self) -> f32 {
match to {
Self::CubicMeters => value,
Self::Liter => value * 1000.0,
Self::USGallon => value / constants::US_GALLON_IN_QUBIC_METER,
}
}
fn to_si(&self, value: &f32) -> f32 {
match self {
Self::CubicMeters => *value,
Self::Liter => value / 1000.0,
Self::USGallon => value * constants::US_GALLON_IN_QUBIC_METER,
}
}
}
pub type Volume = Measurement<f32, VolumeUnit>;
impl Volume {
pub fn cubic_m(value: f32) -> Self {
Measurement {
value,
unit: VolumeUnit::CubicMeters,
}
}
pub fn l(value: f32) -> Self {
Measurement {
value,
unit: VolumeUnit::Liter,
}
}
pub fn gal(value: f32) -> Self {
Measurement {
value,
unit: VolumeUnit::USGallon,
}
}
}
impl Mul<Density> for Volume {
type Output = Mass;
fn mul(self, rhs: Density) -> Self::Output {
let unit = match rhs.unit {
DensityUnit::KilogramPerCubicMeter | DensityUnit::KilogramPerLiter => {
MassUnit::Kilograms
}
};
Mass::from_si(self.to_si() * rhs.to_si(), unit)
}
}