use crate::length::Unit;
use core::fmt;
use core::marker::PhantomData;
use core::ops::{Add, Div, Mul, Sub};
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct Length<U>
where
U: Unit,
{
pub quantity: f64,
unit: PhantomData<U>,
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct Area<U>
where
U: Unit,
{
pub quantity: f64,
unit: PhantomData<U>,
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct Volume<U>
where
U: Unit,
{
pub quantity: f64,
unit: PhantomData<U>,
}
impl_base_ops!(Length, Unit);
impl_base_ops!(Area, Unit);
impl_base_ops!(Volume, Unit);
impl<U> Length<U>
where
U: Unit,
{
pub fn new(quantity: f64) -> Self {
Length::<U> {
quantity,
unit: PhantomData,
}
}
pub fn to<T: Unit>(self) -> Length<T> {
let quantity = self.quantity * U::factor::<T>();
Length::new(quantity)
}
}
impl<U> Area<U>
where
U: Unit,
{
pub fn new(quantity: f64) -> Self {
Area::<U> {
quantity,
unit: PhantomData,
}
}
pub fn to<T: Unit>(self) -> Area<T> {
let factor = U::factor::<T>() * U::factor::<T>();
let quantity = self.quantity * factor;
Area::new(quantity)
}
}
impl<U> Volume<U>
where
U: Unit,
{
pub fn new(quantity: f64) -> Self {
Volume::<U> {
quantity,
unit: PhantomData,
}
}
pub fn to<T: Unit>(self) -> Volume<T> {
let factor = U::factor::<T>() * U::factor::<T>() * U::factor::<T>();
let quantity = self.quantity * factor;
Volume::new(quantity)
}
}
impl<U> fmt::Display for Length<U>
where
U: Unit,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.quantity.fmt(f)?;
write!(f, " {}", U::LABEL)
}
}
impl<U> fmt::Display for Area<U>
where
U: Unit,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.quantity.fmt(f)?;
write!(f, " {}²", U::LABEL)
}
}
impl<U> fmt::Display for Volume<U>
where
U: Unit,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.quantity.fmt(f)?;
write!(f, " {}³", U::LABEL)
}
}
impl<U> Mul for Length<U>
where
U: Unit,
{
type Output = Area<U>;
fn mul(self, other: Self) -> Self::Output {
Area::new(self.quantity * other.quantity)
}
}
impl<U> Mul<Length<U>> for Area<U>
where
U: Unit,
{
type Output = Volume<U>;
fn mul(self, other: Length<U>) -> Self::Output {
Volume::new(self.quantity * other.quantity)
}
}
impl<U> Div<Length<U>> for Area<U>
where
U: Unit,
{
type Output = Length<U>;
fn div(self, other: Length<U>) -> Self::Output {
Length::new(self.quantity / other.quantity)
}
}
impl<U> Div<Length<U>> for Volume<U>
where
U: Unit,
{
type Output = Area<U>;
fn div(self, other: Length<U>) -> Self::Output {
Area::new(self.quantity / other.quantity)
}
}
impl<U> Div<Area<U>> for Volume<U>
where
U: Unit,
{
type Output = Length<U>;
fn div(self, other: Area<U>) -> Self::Output {
Length::new(self.quantity / other.quantity)
}
}