use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DisplayFamily {
Si,
Us,
}
impl QuantityDescriptor {
pub fn label(&self, family: DisplayFamily) -> &'static str {
match family {
DisplayFamily::Si => self.si_label,
DisplayFamily::Us => self.us_label,
}
}
pub fn from_si(&self, si: f64, family: DisplayFamily) -> f64 {
match family {
DisplayFamily::Si => si,
DisplayFamily::Us => self.si_to_us(si),
}
}
pub fn decimals(&self, family: DisplayFamily) -> u8 {
match family {
DisplayFamily::Si => self.si_decimals,
DisplayFamily::Us => self.us_decimals,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct QuantityDescriptor {
pub key: &'static str,
pub si_label: &'static str,
pub us_label: &'static str,
pub si_to_us_scale: f64,
pub si_to_us_offset: f64,
pub si_decimals: u8,
pub us_decimals: u8,
}
impl QuantityDescriptor {
pub fn si_to_us(&self, si: f64) -> f64 {
si * self.si_to_us_scale + self.si_to_us_offset
}
pub fn us_to_si(&self, us: f64) -> f64 {
(us - self.si_to_us_offset) / self.si_to_us_scale
}
}
#[cfg(test)]
mod tests {
use super::*;
const TEMP: QuantityDescriptor = QuantityDescriptor {
key: "temperature",
si_label: "°C",
us_label: "°F",
si_to_us_scale: 1.8,
si_to_us_offset: 32.0,
si_decimals: 1,
us_decimals: 1,
};
#[test]
fn affine_conversion_round_trips() {
assert_eq!(TEMP.si_to_us(100.0), 212.0);
assert_eq!(TEMP.us_to_si(212.0), 100.0);
assert_eq!(TEMP.us_to_si(TEMP.si_to_us(37.5)), 37.5);
}
}