use std::ops::Div;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use super::{
constants, Duration, DurationUnit, Measurement, PhysicalQuantity, UnitOfMeasure, VerticalRate,
VerticalRateUnit,
};
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(C)]
pub enum AltitudeUnit {
Feet,
Meters,
}
impl UnitOfMeasure<f32> for AltitudeUnit {
fn quantity() -> PhysicalQuantity {
PhysicalQuantity::Length
}
fn si() -> Self {
Self::Meters
}
fn symbol(&self) -> &'static str {
match self {
Self::Feet => "ft",
Self::Meters => "m",
}
}
fn from_si(value: f32, to: &Self) -> f32 {
match to {
Self::Meters => value,
Self::Feet => value / constants::FEET_IN_METER,
}
}
fn to_si(&self, value: &f32) -> f32 {
match self {
Self::Meters => *value,
Self::Feet => value * constants::FEET_IN_METER,
}
}
}
pub type Altitude = Measurement<f32, AltitudeUnit>;
impl Altitude {
pub fn ft(value: f32) -> Self {
Self {
value,
unit: AltitudeUnit::Feet,
}
}
pub fn m(value: f32) -> Self {
Self {
value,
unit: AltitudeUnit::Meters,
}
}
}
impl Div<Duration> for Altitude {
type Output = VerticalRate;
fn div(self, rhs: Duration) -> Self::Output {
let mps = self.to_si() / rhs.to_si() as f32;
let unit = match self.unit {
AltitudeUnit::Feet => VerticalRateUnit::FeetPerMinute,
AltitudeUnit::Meters => VerticalRateUnit::MetersPerSecond,
};
VerticalRate::from_si(mps, unit)
}
}
impl Div<VerticalRate> for Altitude {
type Output = Duration;
fn div(self, rhs: VerticalRate) -> Self::Output {
let s = self.to_si() / rhs.to_si();
Duration::from_si(s.round() as u32, DurationUnit::Seconds)
}
}