use crate::{Quantity, Unit};
use qtty_derive::Unit;
pub use crate::dimension::Volume;
pub trait VolumeUnit: Unit<Dim = Volume> {}
impl<T: Unit<Dim = Volume>> VolumeUnit for T {}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "m³", dimension = Volume, ratio = 1.0)]
pub struct CubicMeter;
pub type CubicMeters = Quantity<CubicMeter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "km³", dimension = Volume, ratio = 1e9)]
pub struct CubicKilometer;
pub type CubicKilometers = Quantity<CubicKilometer>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "cm³", dimension = Volume, ratio = 1e-6)]
pub struct CubicCentimeter;
pub type CubicCentimeters = Quantity<CubicCentimeter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "mm³", dimension = Volume, ratio = 1e-9)]
pub struct CubicMillimeter;
pub type CubicMillimeters = Quantity<CubicMillimeter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "L", dimension = Volume, ratio = 1e-3)]
pub struct Liter;
pub type Liters = Quantity<Liter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "mL", dimension = Volume, ratio = 1e-6)]
pub struct Milliliter;
pub type Milliliters = Quantity<Milliliter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "µL", dimension = Volume, ratio = 1e-9)]
pub struct Microliter;
pub type Microliters = Quantity<Microliter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "cL", dimension = Volume, ratio = 1e-5)]
pub struct Centiliter;
pub type Centiliters = Quantity<Centiliter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "dL", dimension = Volume, ratio = 1e-4)]
pub struct Deciliter;
pub type Deciliters = Quantity<Deciliter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "in³", dimension = Volume, ratio = 1.638_706_4e-5)]
pub struct CubicInch;
pub type CubicInches = Quantity<CubicInch>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "ft³", dimension = Volume, ratio = 0.028_316_846_592)]
pub struct CubicFoot;
pub type CubicFeet = Quantity<CubicFoot>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "gal", dimension = Volume, ratio = 0.003_785_411_784)]
pub struct UsGallon;
pub type UsGallons = Quantity<UsGallon>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "fl oz", dimension = Volume, ratio = 2.957_352_956_25e-5)]
pub struct UsFluidOunce;
pub type UsFluidOunces = Quantity<UsFluidOunce>;
#[cfg(test)]
mod tests {
use super::*;
use approx::assert_abs_diff_eq;
#[test]
fn liter_to_cubic_meter() {
let l = Liters::new(1.0);
let m: CubicMeters = l.to();
assert_abs_diff_eq!(m.value(), 0.001, epsilon = 1e-15);
}
#[test]
fn milliliter_to_liter() {
let ml = Milliliters::new(1000.0);
let l: Liters = ml.to();
assert_abs_diff_eq!(l.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn cubic_cm_to_ml() {
let cc = CubicCentimeters::new(1.0);
let ml: Milliliters = cc.to();
assert_abs_diff_eq!(ml.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn us_gallon_to_liter() {
let g = UsGallons::new(1.0);
let l: Liters = g.to();
assert_abs_diff_eq!(l.value(), 3.785_411_784, epsilon = 1e-6);
}
#[test]
fn cubic_foot_to_liter() {
let cf = CubicFeet::new(1.0);
let l: Liters = cf.to();
assert_abs_diff_eq!(l.value(), 28.316_846_592, epsilon = 1e-6);
}
#[test]
fn length_times_area_to_volume() {
use crate::area::{SquareMeter, SquareMeters};
use crate::length::{Meter, Meters};
use crate::Prod;
let side = Meters::new(3.0);
let face: SquareMeters = (side * side).to();
let vol_prod: Quantity<Prod<SquareMeter, Meter>> = face * side;
let vol: CubicMeters = vol_prod.to();
assert_abs_diff_eq!(vol.value(), 27.0, epsilon = 1e-12);
}
#[test]
fn cubic_km_to_liter() {
let ckm = CubicKilometers::new(1.0);
let l: Liters = ckm.to();
assert_abs_diff_eq!(l.value(), 1e12, epsilon = 1e3);
}
#[test]
fn cubic_mm_to_cubic_cm() {
let mm3 = CubicMillimeters::new(1000.0);
let cm3: CubicCentimeters = mm3.to();
assert_abs_diff_eq!(cm3.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn microliter_to_milliliter() {
let ul = Microliters::new(1000.0);
let ml: Milliliters = ul.to();
assert_abs_diff_eq!(ml.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn centiliter_to_liter() {
let cl = Centiliters::new(100.0);
let l: Liters = cl.to();
assert_abs_diff_eq!(l.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn deciliter_to_liter() {
let dl = Deciliters::new(10.0);
let l: Liters = dl.to();
assert_abs_diff_eq!(l.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn cubic_inch_to_cubic_cm() {
let cin = CubicInches::new(1.0);
let cc: CubicCentimeters = cin.to();
assert_abs_diff_eq!(cc.value(), 16.387_064, epsilon = 1e-4);
}
#[test]
fn us_fluid_ounce_to_milliliter() {
let floz = UsFluidOunces::new(1.0);
let ml: Milliliters = floz.to();
assert_abs_diff_eq!(ml.value(), 29.573_529_562_5, epsilon = 1e-6);
}
#[test]
fn symbols_are_correct() {
assert_eq!(CubicMeter::SYMBOL, "m³");
assert_eq!(Liter::SYMBOL, "L");
assert_eq!(Milliliter::SYMBOL, "mL");
assert_eq!(UsGallon::SYMBOL, "gal");
}
}