use crate::{Quantity, Unit};
use qtty_derive::Unit;
pub use crate::dimension::AmountOfSubstance;
pub trait AmountUnit: Unit<Dim = AmountOfSubstance> {}
impl<T: Unit<Dim = AmountOfSubstance>> AmountUnit for T {}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "mol", dimension = AmountOfSubstance, ratio = 1.0)]
pub struct Mole;
pub type Mol = Mole;
pub type Moles = Quantity<Mol>;
pub const MOLE: Moles = Moles::new(1.0);
macro_rules! si_mole {
($name:ident, $sym:literal, $ratio:expr, $alias:ident, $qty:ident, $one:ident) => {
#[doc = concat!("SI-prefixed mole unit (", stringify!($ratio), " mol).")]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = $sym, dimension = AmountOfSubstance, ratio = $ratio)]
pub struct $name;
#[doc = concat!("Type alias shorthand for [`", stringify!($name), "`].")]
pub type $alias = $name;
#[doc = concat!("A quantity measured in ", stringify!($name), ".")]
pub type $qty = Quantity<$alias>;
#[doc = concat!("One ", stringify!($name), ".")]
pub const $one: $qty = $qty::new(1.0);
};
}
si_mole!(Nanomole, "nmol", 1e-9, Nmol, Nanomoles, NANOMOLE);
si_mole!(Micromole, "µmol", 1e-6, Umol, Micromoles, MICROMOLE);
si_mole!(Millimole, "mmol", 1e-3, Mmol, Millimoles, MILLIMOLE);
si_mole!(Kilomole, "kmol", 1e3, Kmol, Kilomoles, KILOMOLE);
#[macro_export]
#[doc(hidden)]
macro_rules! amount_units {
($cb:path) => {
$cb!(Mole, Nanomole, Micromole, Millimole, Kilomole);
};
}
amount_units!(crate::impl_unit_from_conversions);
#[cfg(feature = "cross-unit-ops")]
amount_units!(crate::impl_unit_cross_unit_ops);
#[cfg(test)]
amount_units!(crate::assert_units_are_builtin);
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
use approx::assert_abs_diff_eq;
#[test]
fn millimole_to_mole() {
let mmol = Millimoles::new(1_000.0);
let mol: Moles = mmol.to();
assert_abs_diff_eq!(mol.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn kilomole_to_mole() {
let kmol = Kilomoles::new(1.0);
let mol: Moles = kmol.to();
assert_abs_diff_eq!(mol.value(), 1_000.0, epsilon = 1e-9);
}
#[test]
fn micromole_to_nanomole() {
let umol = Micromoles::new(1.0);
let nmol: Nanomoles = umol.to();
assert_abs_diff_eq!(nmol.value(), 1_000.0, epsilon = 1e-9);
}
}